Created
September 4, 2013 15:59
-
-
Save suryart/6439102 to your computer and use it in GitHub Desktop.
Locating the route of the shortest path of a map(connected nodes with weight/distance) in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# !/usr/bin/ruby1.9.2 | |
# encoding: utf-8 | |
class Node | |
attr_accessor :src, :dst, :length | |
def initialize(src, dst, length = 1) | |
@src = src | |
@dst = dst | |
@length = length | |
end | |
def value | |
{ dst => length } | |
end | |
CLASS1 = %w(A B C D) | |
CLASS2 = %w(E F G H) | |
CLASS3 = %w(I J K L) | |
CLASS4 = %w(M N O P) | |
CLASSES = [CLASS1, CLASS2, CLASS3, CLASS4] | |
end | |
# !/usr/bin/ruby1.9.2 | |
# encoding: utf-8 | |
class Graph < Array | |
attr_reader :nodes | |
def initialize | |
@nodes = {} | |
end | |
def connect_nodes(node1, node2, length = 1) | |
connect node1, node2, length | |
connect node2, node1, length | |
end | |
def neighbors(node) | |
return [] if node.blank? | |
@nodes.map{ |n, v| v.keys if node == n }.flatten.uniq.reject(&:blank?) | |
end | |
def path_between(src, dst) | |
return [] unless self.include?(src) || self.include?(dst) | |
path_hash = @nodes.clone | |
path_hash.keys.each{ |k| path_hash[k] = path_hash[k].keys } | |
find_path(path_hash, src, dst) | |
end | |
private | |
def connect(src, dst, length = 1) | |
unless self.include?(src) | |
raise ArgumentException, "No such vertex: #{src}" | |
end | |
unless self.include?(dst) | |
raise ArgumentException, "No such vertex: #{dst}" | |
end | |
if @nodes[src].blank? | |
@nodes.merge!({ src => Node.new(src, dst, length).value}) | |
else | |
@nodes[src].merge!(Node.new(src, dst, length).value) | |
end | |
end | |
def find_path(path_hash, src, dst) | |
paths = [[src]] | |
loop do | |
paths = paths.flat_map do |path| | |
path_hash[path.last].map do |nekst| | |
nested_path = [*path, nekst] | |
nested_path.last == dst ? (return nested_path) : nested_path | |
end | |
end | |
end | |
end | |
end | |
graph = Graph.new | |
Node::CLASSES.flatten.each {|node| self.push node } | |
Node::CLASSES.each{ |nodes| nodes.each_with_index { |node,i| self.connect_nodes node, nodes[i+1] if i+1 < nodes.length } } | |
Node::CLASSES.transpose.each{ |nodes| nodes.each_with_index { |node,i| self.connect_nodes node, nodes[i+1] if i+1 < nodes.length } } | |
graph.path_between(src, dst) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment