Module: Algorithm
- Defined in:
- lib/ext/algorithm.rb,
lib/ext/shortest_path.rb
Class Method Summary collapse
- .follow(object, sym = nil, &block) ⇒ Object
-
.shortest_path(edges, from, to) ⇒ Object
Return (one of) the shortest path from
fromtotoas a list of edges.
Class Method Details
.follow(object, sym = nil, &block) ⇒ Object
3 4 5 6 7 8 9 10 11 |
# File 'lib/ext/algorithm.rb', line 3 def follow(object, sym = nil, &block) sym.nil? == block_given? or raise "Can't use both symbol and block" a = [] while object a << object object = block_given? ? yield(object) : object.send(sym) end a end |
.shortest_path(edges, from, to) ⇒ Object
Return (one of) the shortest path from from to to as a list of edges. edges is a list of arrays with from-node and to-node as the first two elements. Returns nil if no route was found
The algorithm does slightly more work than it needs to because the same node can be inserted more than once into the queue of nodes to be processed
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 |
# File 'lib/ext/shortest_path.rb', line 10 def self.shortest_path(edges, from, to) pool = {} # Map from 'from' to map from 'to' to edge. Eg. pool[from][to] == edge-between-them edges.each { |edge| (pool[edge[0]] ||= {})[edge[1]] = edge } visited = {} prev = {} todo = [from] while true return nil if todo.empty? current = todo.shift break if current == to next if visited[current] visited[current] = true next if pool[current].nil? pool[current].each { |node, edge| prev[node] ||= edge todo << node } end to_node = to route = [] while edge = prev[to_node] to_node = edge.first route.unshift edge break if from == to_node end route end |