Skip to content

Instantly share code, notes, and snippets.

@joaofnds
Last active August 15, 2017 16:42
Show Gist options
  • Save joaofnds/2ce763c135d2dc9d0bdfa76ffcdcd498 to your computer and use it in GitHub Desktop.
Save joaofnds/2ce763c135d2dc9d0bdfa76ffcdcd498 to your computer and use it in GitHub Desktop.
Simple Dijkstra shortest path algorithm implementation using Crystal
struct Vertex
property id, edges
def initialize(@id : Int32)
@edges = Hash(Pointer(Vertex), Float64).new
end
end
def find(graph : Array(Pointer(Vertex)), start : Pointer(Vertex), end : Pointer(Vertex))
dist = {} of Pointer(Vertex) => Float64 # Distances
prev = {} of Pointer(Vertex) => Pointer(Vertex) # Path
vertices = [] of Pointer(Vertex) # Universe of vertices
graph.each do |vertex|
dist[vertex] = Float64::INFINITY
vertices << vertex
end
dist[start] = 0.to_f
while !vertices.empty?
min_v = dist
.select{|v,_| vertices.includes?(v) }
.min_by{ |_, e| e }
.first
vertices.delete(min_v)
min_v.value.edges.each do |v, e|
alt = dist[min_v] + e
if alt < dist[v]
dist[v] = alt
prev[v] = min_v
end
end
end
return dist, prev
end
module Dijkstra
NUM_OF_VERTICES = 1000;
MAX_EDGES = 10;
MIN_EDGES = 1;
graph = [] of Pointer(Vertex)
(1..NUM_OF_VERTICES).each do |letter|
vertex = Slice(Vertex).new 1, Vertex.new letter
graph << vertex.to_unsafe
end
# Populate graph randomly
graph.each do |vertex|
edges = graph
.reject{ |n| n === vertex }
.sample(Random.rand(1..5))
edges.each do |n|
vertex.value.edges[n] = Random.rand(MIN_EDGES..MAX_EDGES).to_f
end
end
start = graph[Random.rand(NUM_OF_VERTICES)]
finish = graph[Random.rand(NUM_OF_VERTICES)]
dist, path = find(graph, start, finish)
curr = finish
patArr = [] of Int32
while curr != start
patArr << curr.value.id
curr = path[curr]
end
patArr << curr.value.id
puts "start: #{start.value.id}, finish: #{finish.value.id}"
puts "path #{patArr.reverse.join(" => ")}"
puts "distance #{dist[finish]}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment