Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
79
Task/Dijkstras-algorithm/Nim/dijkstras-algorithm.nim
Normal file
79
Task/Dijkstras-algorithm/Nim/dijkstras-algorithm.nim
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Dijkstra algorithm.
|
||||
|
||||
from algorithm import reverse
|
||||
import sets
|
||||
import strformat
|
||||
import tables
|
||||
|
||||
type
|
||||
Edge = tuple[src, dst: string; cost: int]
|
||||
Graph = object
|
||||
vertices: HashSet[string]
|
||||
neighbours: Table[string, seq[tuple[dst: string, cost: float]]]
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc initGraph(edges: openArray[Edge]): Graph =
|
||||
## Initialize a graph from an edge list.
|
||||
## Use floats for costs in order to compare to Inf value.
|
||||
|
||||
for (src, dst, cost) in edges:
|
||||
result.vertices.incl(src)
|
||||
result.vertices.incl(dst)
|
||||
result.neighbours.mgetOrPut(src, @[]).add((dst, cost.toFloat))
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc dijkstraPath(graph: Graph; first, last: string): seq[string] =
|
||||
## Find the path from "first" to "last" which minimizes the cost.
|
||||
|
||||
var dist = initTable[string, float]()
|
||||
var previous = initTable[string, string]()
|
||||
var notSeen = graph.vertices
|
||||
for vertex in graph.vertices:
|
||||
dist[vertex] = Inf
|
||||
dist[first] = 0
|
||||
|
||||
while notSeen.card > 0:
|
||||
# Search vertex with minimal distance.
|
||||
var vertex1: string
|
||||
var mindist = Inf
|
||||
for vertex in notSeen:
|
||||
if dist[vertex] < mindist:
|
||||
vertex1 = vertex
|
||||
mindist = dist[vertex]
|
||||
if vertex1 == last:
|
||||
break
|
||||
notSeen.excl(vertex1)
|
||||
# Find shortest paths to neighbours.
|
||||
for (vertex2, cost) in graph.neighbours.getOrDefault(vertex1):
|
||||
if vertex2 in notSeen:
|
||||
let altdist = dist[vertex1] + cost
|
||||
if altdist < dist[vertex2]:
|
||||
# Found a shorter path to go to vertex2.
|
||||
dist[vertex2] = altdist
|
||||
previous[vertex2] = vertex1 # To go to vertex2, go through vertex1.
|
||||
|
||||
# Build the path.
|
||||
var vertex = last
|
||||
while vertex.len > 0:
|
||||
result.add(vertex)
|
||||
vertex = previous.getOrDefault(vertex)
|
||||
result.reverse()
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc printPath(path: seq[string]) =
|
||||
## Print a path.
|
||||
stdout.write(fmt"Shortest path from '{path[0]}' to '{path[^1]}': {path[0]}")
|
||||
for i in 1..path.high:
|
||||
stdout.write(fmt" → {path[i]}")
|
||||
stdout.write('\n')
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
let graph = initGraph([("a", "b", 7), ("a", "c", 9), ("a", "f", 14),
|
||||
("b", "c", 10), ("b", "d", 15), ("c", "d", 11),
|
||||
("c", "f", 2), ("d", "e", 6), ("e", "f", 9)])
|
||||
printPath(graph.dijkstraPath("a", "e"))
|
||||
printPath(graph.dijkstraPath("a", "f"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue