I am trying to locate the route of the shortest path of a map(connected nodes with weight/distance).
Let's assume I have a hash like this:
{"A"=>{"B"=>1, "E"=>1}, "B"=>{"A"=>1, "C"=>1, "F"=>1}, "C"=>{"B"=>1, "D"=>1, "G"=>1}, "D"=>{"C"=>1, "H"=>1}, "E"=>{"F"=>1, "A"=>1, "I"=>1}, "F"=>{"E"=>1, "G"=>1, "B"=>1, "J"=>1}, "G"=>{"F"=>1, "H"=>1, "C"=>1, "K"=>1}, "H"=>{"G"=>1, "D"=>1, "L"=>1}, "I"=>{"J"=>1, "E"=>1, "M"=>1}, "J"=>{"I"=>1, "K"=>1, "F"=>1, "N"=>1}, "K"=>{"J"=>1, "L"=>1, "G"=>1, "O"=>1}, "L"=>{"K"=>1, "H"=>1, "P"=>1}, "M"=>{"N"=>1, "I"=>1}, "N"=>{"M"=>1, "O"=>1, "J"=>1}, "O"=>{"N"=>1, "P"=>1, "K"=>1}, "P"=>{"O"=>1, "L"=>1}}
Now I want to traverse and make a path from this hash. For example:
From Source A to Destination: L
Output should be: either A -> E -> I -> J -> K -> L
or A -> B -> C -> D -> H -> L
.
Here is the function I wrote:
def find_path(src, dst, init = [])
path = [src]
neighbors = self.neighbors(src)
puts "src: #{src}"
puts "dst: #{dst}"
# puts "node: #{node}"
puts "init: #{init}"
puts "path: #{path}"
puts "----\n"
if neighbors.include?(dst)
path.push(dst)
else
path.push(@nodes[src].keys.map{|k| k unless init.flatten.include? k }.reject(&:blank?).each{|key| self.find_path(key, dst, init << path) } )
end
return path
end
But, this prints only : ["A", ["B", "E"]]
Which is not the desired output, can anybody tell me how do I go make this work? Thanks.
Update: This was used for locating the route of the shortest path of a map(connected nodes with weight/distance). Here are the details on what I was trying to achieve in this question: https://gist.github.com/suryart/6439102
The original hash:
h = {"A"=>{"B"=>1, "E"=>1}, "B"=>{"A"=>1, "C"=>1, "F"=>1}, "C"=>{"B"=>1, "D"=>1, "G"=>1}, "D"=>{"C"=>1, "H"=>1}, "E"=>{"F"=>1, "A"=>1, "I"=>1}, "F"=>{"E"=>1, "G"=>1, "B"=>1, "J"=>1}, "G"=>{"F"=>1, "H"=>1, "C"=>1, "K"=>1}, "H"=>{"G"=>1, "D"=>1, "L"=>1}, "I"=>{"J"=>1, "E"=>1, "M"=>1}, "J"=>{"I"=>1, "K"=>1, "F"=>1, "N"=>1}, "K"=>{"J"=>1, "L"=>1, "G"=>1, "O"=>1}, "L"=>{"K"=>1, "H"=>1, "P"=>1}, "M"=>{"N"=>1, "I"=>1}, "N"=>{"M"=>1, "O"=>1, "J"=>1}, "O"=>{"N"=>1, "P"=>1, "K"=>1}, "P"=>{"O"=>1, "L"=>1}}
Converting the original hash since its format sucks:
h.keys.each{|k| h[k] = h[k].keys}
h.default = []
The method:
def find_path h, src, dst
paths = [[src]]
loop do
paths = paths.flat_map do |path|
h[path.last].map do |nekst|
a = [*path, nekst]
a.last == dst ? (return a) : a
end
end
end
end
Trying it:
find_path(h, "A", "L")
# => ["A", "B", "C", "D", "H", "L"]
Notice that if there is no solution, then the loop may run forever. You might want to limit that by adding a limit to the length.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.