summaryrefslogtreecommitdiff
path: root/chapter25/docs/examples/Dijkstra.smp
blob: fd595eb5769795cc2dc876fa86ad5b8c4c8550ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

// An implementation of
// https://sampleprograms.io/projects/dijkstra/

val shortestPath = { !sys.aryi64 matrix, int nodes, int src, int dst ->
    i64 infinity = (1 << 63)-1;
    var dist = new i64[nodes];
    var visited = new sys.adt.bitset();
    // All nodes are infinitely far from each other
    for( int i=0; i<nodes; i++ ) dist[i] = infinity;
    // Starting point is zero far from starting point
    dist[src] = 0;

    i64 result = -1;
    int count = 0;
    while( count < nodes && result < 0 ) {
        int nearest = -1;
        i64 best = infinity;
        for( int node=0; node<nodes; node++ )
            if( !visited.get(node) && dist[node] < best ) {
                nearest = node;
                best = dist[node];
            }
        if( nearest < 0 ) count = nodes;
        else {
            if( nearest == dst ) return best;
            visited.set(nearest);
            for( int node=0; node<nodes; node++ ) {
                i64 weight = matrix.get(nearest*nodes + node);
                if( weight > 0 && !visited.get(node) && best+weight < dist[node] )
                    dist[node] = best+weight;
            }
        }
        count++;
    }
    return result;
};

val usage = { ->
    sys.io.p("Usage: please provide three inputs: a serialized matrix, a source node and a destination node\n");
    return 0;
};

val main = { u8[~][] args ->
    // Exactly 3 args
    if( args# != 4 ) return usage();
    // First is a serialized square matrix of positive numbers
    var matrix = sys.aryi64.parseAryI64(args[1]);
    if( !matrix ) return usage();
    if( !matrix.len ) return usage();
    // All numbers are positive
    for( int i=0; i<matrix.len; i++ )
        if( matrix.get(i) < 0 ) return usage();
    // Matrix is square
    int nodes = 0;
    while( nodes*nodes < matrix.len ) nodes++;
    if( nodes*nodes != matrix.len )
        return usage();         // Not a square matrix

    // src,dst are values within the matrix
    i64 src = sys.aryu8.atoi(args[2]);
    i64 dst = sys.aryu8.atoi(args[3]);
    if( src < 0 || src >= nodes || dst < 0 || dst >= nodes )
        return usage();         // Source and destination land within the graph

     i64 cost = shortestPath(matrix,nodes,src,dst);
     if( cost >= 0 ) {
         new sys.aryu8().num(cost).add('\n').write(1);
         return 0;
     }
    return usage();
};