diff --git a/dijk.c b/dijk.c new file mode 100644 index 0000000..c89f579 --- /dev/null +++ b/dijk.c @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: MIT */ + +/* + * Imbus 2025 + * + * PQ-less dijkstra in quadratic complexity + */ + +#include +#include + +#define DIM 26 + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 +#define F 5 +#define G 6 +#define H 7 +#define I 8 +#define J 9 +#define K 10 +#define L 11 +#define M 12 +#define N 13 +#define O 14 +#define P 15 +#define Q 16 +#define R 17 +#define S 18 +#define T 19 +#define U 20 +#define V 21 +#define W 22 +#define X 23 +#define Y 24 +#define Z 25 + +/* Node to character */ +#define ntoch(n) ('A' + (char)(n % 26)) + +/* Some helpers */ +#define set_dist(from, to, d) g[((int)from)][((int)to)] = (int)d +#define get_dist(from, to) g[((int)from)][((int)to)] + +/* Adjacency matrix */ +int g[DIM][DIM] = {}; + +void printmat(int mat[DIM][DIM]) { + printf("## "); + for (int h = 0; h < DIM; h++) printf("%c ", ntoch(h)); + printf("\n"); + printf(" "); + for (int h = 0; h < DIM; h++) printf("%s", "__"); + printf("\n"); + for (int i = 0; i < DIM; i++) { + printf("%c |", ntoch(i)); + for (int j = 0; j < DIM; j++) { + printf("%c ", ntoch(mat[i][j])); + } + printf("\n"); + } +} + +void dijkstra(int mat[DIM][DIM], int prev[DIM], int dist[DIM], int s) { + int visited[DIM] = {0}; + + for (int i = 0; i < DIM; i++) { + dist[i] = INT_MAX; + prev[i] = -1; + } + + dist[s] = 0; + prev[s] = 0; + + for (int i = 0; i < DIM; i++) { + // Pick first unvisited with smallest dist + int u = -1; + int min = INT_MAX; + + for (int j = 0; j < DIM; j++) { + if (!visited[j] && dist[j] < min) { + min = dist[j]; + u = j; + } + } + + if (u == -1) + break; + visited[u] = 1; + + for (int v = 0; v < DIM; v++) { + if (get_dist(u, v) > 0 && !visited[v]) { + if (dist[u] + get_dist(u, v) < dist[v]) { + dist[v] = dist[u] + get_dist(u, v); + prev[v] = u; + } + } + } + } +} + +void path_reconstruct(int prev[DIM], int dist[DIM], int s, int t) { + if (dist[t] == INT_MAX) { + printf("No path from %c to %c\n", ntoch(s), ntoch(t)); + return; + } + + int path[DIM]; + int len = 0; + + // Walk backwards from target to source + for (int v = t; v != -1; v = prev[v]) { + path[len++] = v; + if (v == s) + break; + } + + if (path[len - 1] != s) { + printf("No path from %c to %c\n", ntoch(s), ntoch(t)); + return; + } + + // Print path in correct order + printf("Path (cost %d): ", dist[t]); + for (int i = len - 1; i >= 0; i--) { + printf("%c", ntoch(path[i])); + if (i > 0) + printf(" -> "); + } + printf("\n"); +} + +void init_graph(void) { + set_dist(A, B, 4); + set_dist(A, C, 9); + set_dist(B, D, 2); + set_dist(B, E, 5); + set_dist(C, B, 2); + set_dist(C, F, 7); + set_dist(D, C, 1); + set_dist(E, C, 2); + set_dist(F, G, 3); + set_dist(G, H, 6); + set_dist(H, I, 1); + set_dist(I, J, 8); + set_dist(J, K, 4); + set_dist(K, L, 5); + set_dist(L, M, 2); + set_dist(M, N, 3); + set_dist(N, O, 7); + set_dist(O, P, 1); + set_dist(P, Q, 2); + set_dist(Q, R, 6); + set_dist(R, S, 3); + set_dist(S, T, 5); + set_dist(T, U, 2); + set_dist(U, V, 1); + set_dist(V, W, 4); + set_dist(W, X, 7); + set_dist(X, Y, 2); + set_dist(Y, Z, 3); + set_dist(Z, A, 8); +} + +int main(void) { + for (int i = 0; i < DIM; i++) { + for (int j = 0; j < DIM; j++) { + g[i][j] = -1; + } + } + + init_graph(); + + printmat(g); + + int prev[DIM] = {0}; + int dist[DIM] = {0}; + dijkstra(g, prev, dist, A); + + for (int k = 0; k < DIM; k++) { + printf("%c prev: %c\n", ntoch(k), ntoch(prev[k])); + } + + path_reconstruct(prev, dist, A, Z); +}