Skip to content

Instantly share code, notes, and snippets.

@suryart
Created September 4, 2013 15:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suryart/6439102 to your computer and use it in GitHub Desktop.
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
# !/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