Here is my solution, very much a derivative of my solution to the
Knight's Travails quiz (#27). It will return a shortest solution
(chosen at random if there are more than one). It will always find a
shortest solution, though not necessarily fast. (I haven't tried timing
this.)



# Helper methods
class Integer
   def even?
      self & 1 == 0
   end

   def maze_adj
      if even?
         [self + 2, self * 2, self / 2]
      else
         [self + 2, self * 2]
      end
   end
end


def solve(a, b)
   i = 0
   steps = [[a]]

   # steps[i] contains all the numbers reachable in i steps
   until steps[i].include?(b)
      i += 1
      steps[i] = []
      steps[i-1].each do |x|
         steps[i].concat x.maze_adj
      end
   end

   # path is built in reverse order, finding a legal previous
   # number according to "adjacency" rules
   i -= 1
   path = [b]
   i.downto(0) do |k|
      s = steps[k].find_all { |x| x.maze_adj.include? path.last }
      path << s.sort_by { rand }.first
   end

   # path was built in reverse order, so reverse to get the final path
   path.reverse
end


# Examples
p solve(2, 9)
p solve(9, 2)