Skip to content

Commit 0df119c

Browse files
authored
Add Dijkstra in PowerShell (TheRenegadeCoder#4854)
1 parent 2bba5cd commit 0df119c

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

archive/p/powershell/Dijkstra.ps1

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
function Show-Usage() {
2+
Write-Host "Usage: please provide three inputs: a serialized matrix, a source node and a destination node"
3+
Exit(1)
4+
}
5+
6+
function Parse-IntList([string]$Str) {
7+
@($Str.Split(",") | ForEach-Object { [int]::Parse($_) })
8+
}
9+
10+
function Test-Inputs([array]$Weights, [int]$NumVertices, [int]$Src, [int]$Dest) {
11+
# Verify number of weights is a square, weights are non-negative, any non-zero weight, and source
12+
# destination are valid
13+
$WeightMeasurements = $Weights | Measure-Object -Minimum -Maximum
14+
($Weights.Length -eq ($NumVertices * $NumVertices) -and
15+
$WeightMeasurements.Minimum -ge 0 -and
16+
$WeightMeasurements.Maximum -gt 0 -and
17+
$Src -ge 0 -and $Src -lt $NumVertices -and
18+
$Dest -ge 0 -and $Dest -lt $NumVertices)
19+
}
20+
21+
class NodeItem {
22+
[int]$Index
23+
[int]$Weight
24+
25+
NodeItem([int]$index, [int]$weight) {
26+
$this.Index = $index
27+
$this.Weight = $weight
28+
}
29+
}
30+
31+
class Node {
32+
[int]$Index
33+
[NodeItem[]]$Children
34+
35+
Node([int]$index) {
36+
$this.Index = $index
37+
$this.Children = @()
38+
}
39+
40+
[void] AddChild([int]$index, [int]$weight) {
41+
$this.Children += [NodeItem]::new($index, $weight)
42+
}
43+
}
44+
45+
function Create-Graph([array]$Weights, [int]$NumVertices) {
46+
# Initialize nodes
47+
$nodes = 0..($NumVertices - 1) | ForEach-Object { [Node]::new($_) }
48+
49+
# Get neighbors for this node based on weights
50+
$index = 0
51+
for ($row = 0; $row -lt $NumVertices; $row++) {
52+
for ($col = 0; $col -lt $NumVertices; ($col++), ($index++)) {
53+
if ($Weights[$index] -gt 0) {
54+
$nodes[$row].AddChild($col, $Weights[$index])
55+
}
56+
}
57+
}
58+
59+
$nodes
60+
}
61+
62+
class DijkstraItem {
63+
[int]$Prev = -1
64+
[int]$Dist = [int]::MaxValue
65+
}
66+
67+
# Source: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Pseudocode
68+
function Invoke-Dijkstra([Node[]]$Graph, [int]$Src) {
69+
# Initialize distances to infinite and previous vertices to undefined
70+
$numVertices = $Graph.Length
71+
$results = 0..($numVertices - 1) | ForEach-Object { [DijkstraItem]::new() }
72+
73+
# Indicate all nodes unvisited
74+
$q = [Collections.Generic.HashSet[int]](0..($numVertices - 1))
75+
76+
# Set source vertex distance to 0
77+
$results[$Src].Dist = 0
78+
79+
# While there are unvisited nodes
80+
while ($q.Count) {
81+
# Pick a vertex u with minimum distance from unvisited nodes
82+
$u = Find-MinDistIndex $q $results
83+
84+
# Indicate vertex u visited
85+
[void]$q.Remove($u)
86+
87+
# For each unvisited neighbor v of vertex u
88+
foreach ($node in $Graph[$u].Children) {
89+
$v = $node.Index
90+
if ($v -in $q) {
91+
# Get trial distance
92+
$alt = $results[$u].Dist + $node.Weight
93+
94+
# If trial distance is smaller than distance v, update distance to v and
95+
# previous vertex of v
96+
if ($alt -lt $results[$v].Dist) {
97+
$results[$v].Dist = $alt
98+
$results[$v].Prev = $u
99+
}
100+
}
101+
}
102+
}
103+
104+
$results
105+
}
106+
107+
function Find-MinDistIndex([Collections.Generic.HashSet[int]]$q, [DijkstraItem[]]$results) {
108+
$minDist = [int]::MaxValue
109+
$minIndex = -1
110+
for ($v = 0; $v -lt $results.Length; $v++) {
111+
if ($v -in $q -and $results[$v].Dist -lt $minDist) {
112+
$minDist = $results[$v].Dist
113+
$minIndex = $v
114+
}
115+
}
116+
117+
$minIndex
118+
}
119+
120+
if ($args.Length -lt 3 -or -not $args[0]) {
121+
Show-Usage
122+
}
123+
124+
try {
125+
$weights = Parse-IntList $args[0]
126+
$src = [int]::Parse($args[1])
127+
$dest = [int]::Parse($args[2])
128+
} catch {
129+
Show-Usage
130+
}
131+
132+
133+
$numVertices = [int][Math]::Floor([Math]::Sqrt($weights.Length))
134+
if (-not (Test-Inputs $weights $numVertices $src $dest)) {
135+
Show-Usage
136+
}
137+
138+
# Create graph from weights
139+
$graph = Create-Graph $weights $numVertices
140+
141+
# Run Dijkstra's algorithm on graph and show distance to destination
142+
$results = Invoke-Dijkstra $graph $src
143+
Write-Output $results[$dest].Dist

0 commit comments

Comments
 (0)