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

15 Puzzle

The goal of the 15 puzzle problem is to complete pieces on $4 \times 4$ 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 15 as shown below.

1 2 3 4
6 7 8 0
5 10 11 12
9 13 14 15

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
9 10 11 12
13 14 15 0

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

Input

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

Output

Print the fewest steps in a line.

Constraints

The given puzzle is solvable in at most 45 steps.

Sample Input

1 2 3 4
6 7 8 0
5 10 11 12
9 13 14 15

Sample Output

8

Solution in Ruby (judge verdict: Accepted)

N = 4
N2 = 16
mdt = Array.new(N2){Array.new(N2){0}}

N2.times{|i|
  N2.times{|j|
    mdt[i][j] = ((i / N) - (j / N)).abs + ((i % N) - (j % N)).abs
  }
}

dx = [0, -1, 0, 1]
dy = [1, 0, -1, 0]
mat = Array.new(N2)
space = 0
md = nil
steps = 0;

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

pre_space = mat.index(0)
ini_md = 0
N2.times{|i|
  ini_md += mdt[i][mat[i]-1] unless i == pre_space
}

path = []
criteria = ini_md
tx = 0
ty = 0
mdt_diff = 0
loop do
  break if criteria >= 50;
  space = pre_space
  md = ini_md
  steps = 0
  path[0] = 4
  pre_direc = 0
  while steps >= 0 && md > 0 do
    sx = space / N
    sy = space % N

    direc = pre_direc-1
    loop do
      direc += 1
      break if direc == 4
      next if path[steps] ^ direc == 2
      tx = sx + dx[direc]
      ty = sy + dy[direc]
      next if tx < 0 || ty < 0 || tx == N || ty == N
      mdt_diff = mdt[sx*N+sy][mat[tx*N+ty]-1] - mdt[tx*N+ty][mat[tx*N+ty]-1]
      next if steps + 1 + md + mdt_diff > criteria
      break
    end
    if direc < 4 then
      mat[sx*N+sy], mat[tx*N+ty] = mat[tx*N+ty], mat[sx*N+sy]
      space = tx*N+ty
      md += mdt_diff
      steps += 1
      path[steps] = direc
      pre_direc = 0
    else
      direc = path[steps] ^ 2
      pre_direc = path[steps] + 1
      steps -= 1
      if steps >= 0 then
        rev_space = space + N * dx[direc] + dy[direc]
        md += mdt[space][mat[rev_space]-1] - mdt[rev_space][mat[rev_space]-1]
        mat[space], mat[rev_space] = mat[rev_space], mat[space]
        space = rev_space
      end
    end
  end
  break if steps >= 0
  criteria += 2;
end

puts steps