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 Scala (judge verdict: Accepted)

import java.util
object Main extends App {
  import scala.io.StdIn._
  val goal = new Square(Array(Array(1,2,3), Array(4,5,6), Array(7,8,0)))
  val goalHash = goal.hashCode()
  val start = new Square((0 until 3).map{_ => readLine().trim().split(' ').map(_.toInt).toArray}.toArray)
  println(search(start))
  def search(start:Square):Int = {
    val memo = Array.tabulate(362880){_ => -1}
    var count = 0
    val queue:util.Deque[Square] = new util.LinkedList()
    memo(start.hashCode()) = 0
    queue.addLast(start)
    while (memo(goalHash) < 0){
      count += 1
      for (i <- 0 until queue.size()){
        for (s <- queue.peek().nextCases){
          if (memo(s.hashCode()) < 0){
            memo(s.hashCode()) = count
            queue.addLast(s)
          }
        }
        queue.pop()
      }
    }
    memo(goalHash)
  }
  class Square(private val array:Array[Array[Int]]){
    override def hashCode(): Int = Square.factorial.foldLeft((0, (0 until 3).flatMap{a => (0 until 3).map{b => array(a)(b)}}.toList)){
      case ((s, h::t), f) => (s + f * h, t.map{n => if (n > h) n - 1 else n})
      case (s, f) => s
    }._1
    lazy val zeroPoint:Point = (0 until 3).flatMap{x => (0 until 3).map{y => Point(x, y)}}.filter{case Point(x, y) => array(x)(y) == 0}.head
    def copy:Square = new Square(array.map(_.clone()))
    def nextCases:List[Square] = zeroPoint.neighbors.filter(Square.isValidPoint(_)).map{
      case Point(x, y) =>
        val r = copy
        r.array(zeroPoint.x)(zeroPoint.y) = array(x)(y)
        r.array(x)(y) = 0
        r
    }
  }
  case class Point(x:Int, y:Int){
    def neighbors:List[Point] = List(Point(x - 1, y), Point(x + 1, y), Point(x, y - 1), Point(x, y + 1))
  }
  object Square{
    val factorial = List(40320, 5040, 720, 120, 24, 6, 2, 1, 1)
    def isValidPoint(other:Point):Boolean = (0 until 3).contains(other.x) && (0 until 3).contains(other.y)
  }
}