Skip to content

Commit 695bfb6

Browse files
authored
Add Dijkstra in Tcl (#5048)
1 parent 941ec46 commit 695bfb6

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

archive/t/tcl/dijkstra.tcl

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package require Tcl 8.6
2+
package require struct
3+
package require struct::graph
4+
package require struct::graph::op
5+
6+
proc usage {} {
7+
puts stderr {Usage: please provide three inputs: a serialized matrix, a source node and a destination node}
8+
exit 1
9+
}
10+
11+
proc isInteger {x} { return [string is integer -strict $x] }
12+
13+
proc parseList {s} {
14+
set s [string trim $s]
15+
if {$s eq ""} { usage }
16+
17+
set result {}
18+
foreach t [split $s ,] {
19+
set t [string trim $t]
20+
if {![isInteger $t] || $t < 0} { usage }
21+
lappend result $t
22+
}
23+
return $result
24+
}
25+
26+
proc createGraph {matrix vertices} {
27+
set n [llength $vertices]
28+
if {[llength $matrix] != [expr {$n * $n}]} { usage }
29+
30+
set g [struct::graph]
31+
$g node insert {*}$vertices
32+
33+
set idx 0
34+
foreach i $vertices {
35+
foreach j $vertices {
36+
set w [lindex $matrix $idx]
37+
incr idx
38+
if {$w > 0} {
39+
set a [$g arc insert $i $j]
40+
$g arc setweight $a $w
41+
}
42+
}
43+
44+
return $g
45+
}
46+
}
47+
48+
proc main {argv} {
49+
if {[llength $argv] != 3} { usage }
50+
lassign $argv matrixStr srcStr destStr
51+
52+
if {![string is integer -strict $srcStr] || ![string is integer -strict $destStr]} {
53+
usage
54+
}
55+
56+
set matrix [parseList $matrixStr]
57+
set n [expr {int(sqrt([llength $matrix]))}]
58+
if {$n*$n != [llength $matrix]} { usage }
59+
60+
set src [expr {$srcStr + 0}]
61+
set dest [expr {$destStr + 0}]
62+
if {$src < 0 || $src >= $n || $dest < 0 || $dest >= $n} { usage }
63+
64+
set vertices [lrange [list {*}[lrepeat $n 0]] 0 end]
65+
for {set i 0} {$i < $n} {incr i} { lset vertices $i $i }
66+
67+
set g [createGraph $matrix $vertices]
68+
69+
if {[$g node degree $src] == 0 || [$g node degree $dest] == 0} {
70+
$g destroy
71+
usage
72+
}
73+
74+
try {
75+
set distances [::struct::graph::op::dijkstra $g $src -outputformat distances]
76+
if {[dict exists $distances $dest]} {
77+
puts [dict get $distances $dest]
78+
} else {
79+
usage
80+
}
81+
} on error {err opts} {
82+
usage
83+
} finally {
84+
$g destroy
85+
}
86+
}
87+
88+
main $argv
89+

0 commit comments

Comments
 (0)