```I didn't like having the roof calculation done inside the solve
method.  So here is my revised algorithm, including Dominik's
suggestions and a new roof class method for Integer.

#!/usr/bin/env ruby

class Integer

@@roof = 1.0/0.0

def self.roof(*args)
@@roof = args.max * 2 + 2 || @@roof
end

def odd?
self % 2 != 0
end

# optimized to remove consecutive double/halves and remove
adjacent values greater than a maximum
list = []
list << self * 2 unless @parent == self * 2  or self * 2 > @@roof
list << self / 2 unless self.odd? or @parent == self / 2
list << self + 2 unless self + 2 > @@roof
list
end

def visit!(parent = nil)
@parent = parent
end

def path_from(start)
if self == start
[start]
else
if @parent == nil
raise "no path from #{start} to #{self} exists"
else
@parent.path_from(start) << self
end
end
end
end

def solve(start, target)
return [start] if start == target
Integer.roof(start, target)
start.visit!
queue = [start]
queue.each do |vertex|
unless child.parent
child.visit!(vertex)
return target.path_from(start) if target == child
queue.push(child)
end
end
end
end

# Run this code only when the file is the main program
if \$0 == __FILE__
# Parse arguments (authored by James Edward Gray II)
unless ARGV.size == 2 and ARGV.all? { |n| n =~ /\A[1-9]\d*\Z/ }
puts "Usage:  #{File.basename(\$0)} START_NUMBER FINISH_NUMBER"
puts "  Both number arguments must be positive integers."
exit
end
start, finish = ARGV.map { |n| Integer(n) }

p solve(start, finish)
end

~ ryan ~

```