Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

8 Puzzle

The goal of the 8 puzzle problem is to complete pieces on $3 \times 3$ cells where one of the cells is empty space.

In this problem, the space is represented by 0 and pieces are represented by integers from 1 to 8 as shown below.

1 3 0
4 2 5
7 8 6

You can move a piece toward the empty space at one step. Your goal is to make the pieces the following configuration in the shortest move (fewest steps).

1 2 3
4 5 6
7 8 0

Write a program which reads an initial state of the puzzle and prints the fewest steps to solve the puzzle.

Input

The $3 \times 3$ integers denoting the pieces or space are given.

Output

Print the fewest steps in a line.

Constraints

There is a solution.

Sample Input

1 3 0
4 2 5
7 8 6

Sample Output

4

Solution in Ruby (judge verdict: Accepted)

class Puzzle
  attr_accessor :mat, :step, :cost
  def initialize(mat, step)
    @mat = mat
    @step = step
    @cost = distance
  end
  def >(other)
    return self.cost + self.step < other.cost + other.step ? true : false
  end
  def <(other)
    return self.cost + self.step > other.cost + other.step ? true : false
  end
  def distance
    goal = [1,2,3,4,5,6,7,8,0]
    d = 0
    9.times{|n|
      m = @mat.index(goal[n])
      y1, x1 = n.divmod(3)
      y2, x2 = m.divmod(3)
      d += (y1-y2).abs + (x1-x2).abs
    }
    return d
  end
end

class Heep
  def initialize
    @node = []
  end
  def insert(num)
    i = @node.size
    @node[i] = num
    p = (i+1)/2-1
    while i > 0 && @node[p] < @node[i]
      @node[i], @node[p] = @node[p], @node[i]
      i = p
      p = (i+1)/2-1
    end
  end
  def extract
    ret = @node[0]
    if @node.size > 1
      @node[0] = @node.pop()
      maxHeapify(0)
    else
      @node = []
    end
    return ret
  end
  def maxHeapify(i)
    h = @node.size
    largest = i
    l = 2 * i + 1
    largest = l if l < h && @node[l] > @node[largest]
    r = 2 * i + 2
    largest = r if r < h && @node[r] > @node[largest]
    if largest != i then
      @node[i], @node[largest] = @node[largest], @node[i]
      maxHeapify(largest)
    end
  end
  def size
    return @node.size
  end
  def contain(node)
    if @node.index(node) == nil
      return false
    else
      return true
    end
  end
end

mat = []
3.times{|i|
  mat[3*i],mat[3*i+1],mat[3*i+2] = gets.split.map(&:to_i)
}

ini = Puzzle.new(mat, 0)
q = Heep.new
q.insert(ini)

done = {}
loop do
  break if q.size == 0
  it = q.extract
  if it.cost == 0 then
    p it.step
    exit
  else
    done[it.mat.join("")] = true
  end
  idx = it.mat.index(0)
  y, x = idx.divmod(3)
  #Down
  unless y == 0 then
    mat = it.mat.clone
    mat[idx], mat[idx-3] = mat[idx-3], mat[idx]
    unless done[mat.join]
      tmp = Puzzle.new(mat, it.step+1)
      q.insert(tmp)
    end
  end

  #Up
  unless y == 2 then
    mat = it.mat.clone
    mat[idx], mat[idx+3] = mat[idx+3], mat[idx]
    tmp = Puzzle.new(mat, it.step+1)
    unless done[mat.join]
      tmp = Puzzle.new(mat, it.step+1)
      q.insert(tmp)
    end
  end
  
  #Left
  unless x == 0 then
    mat = it.mat.clone
    mat[idx], mat[idx-1] = mat[idx-1], mat[idx]
    tmp = Puzzle.new(mat, it.step+1)
    unless done[mat.join]
      tmp = Puzzle.new(mat, it.step+1)
      q.insert(tmp)
    end
  end

  #Right
  unless x == 2 then
    mat = it.mat.clone
    mat[idx], mat[idx+1] = mat[idx+1], mat[idx]
    tmp = Puzzle.new(mat, it.step+1)
    unless done[mat.join]
      tmp = Puzzle.new(mat, it.step+1)
      q.insert(tmp)
    end
  end
  
end