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 OCaml (judge verdict: Time Limit Exceeded)

let (n1, n2) = (4, 16)

let area =
  [| [1; 4]; [0; 2; 5]; [1; 3; 6]; [2; 7]
   ; [0; 5; 8]; [1; 4; 6; 9]; [2; 5; 7; 10]; [3; 6; 11]
   ; [4; 9; 12]; [5; 8; 10; 13]; [6; 9; 11; 14]; [7; 10; 15]
   ; [8; 13]; [9; 12; 14]; [10; 13; 15]; [11; 14] |]

let md = Array.make_matrix n2 n2 0

let initialize_md () =
  for i = 0 to n2 - 2 do
    for j = 0 to n2 - 1 do
      md.(i+1).(j) <- abs (i / n1 - j / n1) + abs (i mod n1 - j mod n1)
    done
  done

let idastar a limit space_i lower goal =
  let rec doit i space_i moved lower =
    if i = limit then begin
      if a = goal then begin
        Printf.printf "%d\n" (List.length moved - 1);
        exit 0;
      end
    end else
      List.iter (fun j ->
        let x = a.(j) in
        if x = List.hd moved then () else
        let lower = lower - md.(x).(j) + md.(x).(space_i) in
        if lower + i > limit then ()
        else
          a.(j) <- 0;
          a.(space_i) <- x;
          doit (i + 1) j (x :: moved) lower;
          a.(j) <- x;
          a.(space_i) <- 0) area.(space_i) in
  doit 0 space_i [-1] lower

let () =
  initialize_md ();
  let a = Array.init n2 (fun _ -> Scanf.scanf "%d " (fun i -> i)) in
  let rec f i =
    if i = n2 then assert false
    else if a.(i) = 0 then i
    else f (i + 1) in
  let space_i = f 0 in
  let rec g i acc =
    if i = n2 then acc
    else g (i + 1) (acc + md.(a.(i)).(i)) in
  let lower = g 0 0 in
  let goal = [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 0|] in
  for limit = lower to 45 do
    idastar a limit space_i lower goal
  done