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

{-# LANGUAGE FlexibleContexts #-}

module Main where

-- import Debug.Trace
import Data.List
import qualified Data.Set as Set
import qualified Data.Sequence as Seq
import qualified Data.ByteString.Char8 as B
import Data.Int
import Data.Word
import Data.Char
import Data.Bits
import Data.Array
-- import Data.Array.Unboxed
-- import Data.Array.IO
import Data.Maybe
-- import qualified Data.Map as M
import qualified Data.IntMap as M
-- import Control.Monad.ST
-- import Data.STRef
import Data.Ord
import Data.Functor
import Control.Applicative
import Control.Monad
import Text.Printf

size = 3
maxAdr = size*size -1

solver :: [[Int]] -> Int
solver lst = bfs start goalID where
    bfs start goalID = iter ((Seq.singleton (start, generateID start, 0)), M.empty) where
        iter (que, visited) = case Seq.viewr que of
            Seq.EmptyR -> error "No path found."
            que Seq.:> path@(b, bId, d)
                | bId == goalID -> d
                | otherwise -> iter (insertPaths que visited (nextPaths path)) where
                    insertPaths q v [] = (q, v)
                    insertPaths q v (p@(_,x,_):ps) = insertPaths (p Seq.<| q) (M.insert x () visited) ps
                    nextPaths path@(b, bId, d) = [(x, xId, d+1)| (x, xId) <- nextBoards, notVisited xId] where        
                        notVisited x = M.notMember x visited
                        boards = [swapAt (b !! q) b | q <- dest!p]
                        nextBoards = [(x, generateID x)| x <- boards]
                        p = fromJust $ elemIndex 0 b
    goalID= generateID [1,2,3,4,5,6,7,8,0]
    start = concat lst
    dest  = listArray (0, maxAdr) [[1,3],[0,2,4],[1,5],[0,4,6],[1,3,5,7],[2,4,8],[3,7],[4,6,8],[5,7]] 
    generateID board = foldl' (\b a-> shiftL b 4 .|. a) 0 board

swapAt :: Int -> [Int] -> [Int]
swapAt v = foldr (\a b -> case a of
    _   | a == 0 -> v:b
        | a == v -> 0:b
        | otherwise -> a:b
     ) [] 

readIntLn:: IO Int
readIntLn = (fst . fromJust . B.readInt) <$> B.getLine

readIntList:: IO [Int]
readIntList = map (fst . fromJust . B.readInt) . B.words <$> B.getLine

main :: IO() 
main = do
    l <- replicateM size readIntList
    print $ solver l