-
Notifications
You must be signed in to change notification settings - Fork 0
/
dijkstra.rb
53 lines (40 loc) · 1.22 KB
/
dijkstra.rb
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
require_relative 'dijkstra/data'
# See https://github.com/RichOrElse/wrapper-based/blob/master/test/dijkstra_test.rb
module DestinationNode
def shortest_path_from(node, finds_shortest)
return [self] if equal? node
finds_shortest.path from: node
end
end
module Map
def distance_between(a, b)
@distances[Edge.new(a, b)]
end
def neighbors_of(node)
[south_neighbor_of(node), east_neighbor_of(node)].compact
end
end
class FindsDistance < DCI::Context(city: Map)
def initialize(city) super(city: city) end
def between(from, to)
city.distance_between(from, to)
end
def of(path)
path.each_cons(2).inject(0) { |total_distance, (to, from)| total_distance + between(from, to) }
end
alias_method :call, :of
end
class FindsShortest < DCI::Context(:from, to: DestinationNode, city: Map, road_distance: FindsDistance)
def initialize(city:, from: city.root, to: city.destination, road_distance: city) super end
def distance
road_distance.of path
end
def path(from: @from)
city.neighbors_of(from).map(&to_shortest_path).min_by(&road_distance) << from
end
def call(neighbor = @from)
to.shortest_path_from(neighbor, self)
end
private
alias_method :to_shortest_path, :to_proc
end