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 C# (judge verdict: Wrong Answer)

using System;
using System.Linq;
using System.Collections.Generic;

public class Program{
    public static void Main(){
        var Board = new int[3, 3];
        for(int i=0; i<3; i++){
            var line = Console.ReadLine().Split().Select(int.Parse).ToArray();
            for(int j=0; j<3; j++){
                Board[i, j] = line[j];
            }
        }
        var Goal = new int[,]{ {1, 2, 3}, {4, 5, 6}, {7, 8, 0} };
        var queue = new Queue<State>();
        var all_list = new List<string>();
        queue.Enqueue(new State{table = Board, cnt = 0});
        int c = 0;
        while(queue.Count()>0&&c<500){
            var curr = queue.Dequeue();
            //Print(curr.table);
            if(all_list.Contains(ToStringForList(curr.table)))continue;
            else all_list.Add(ToStringForList(curr.table));
            if(curr.table.ContentEqual(Goal)){
                Console.WriteLine(curr.cnt);
                break;
            }
            
            var Now = curr.GetPos();
            var cx = Now.X;
            var cy = Now.Y;
            var steps = new int[]{0, 1, 0, -1, 0};
            for(int i=0; i<4; i++){
                var nx = cx+steps[i]; 
                var ny = cy+steps[i+1];
                if(0<=nx && nx<Board.GetLength(1) && 0<=ny && ny<Board.GetLength(0)){
                    var Nex = new Pos{Y = ny, X = nx};
                    var NexMap = curr.Swap(Nex, Now);
                    queue.Enqueue(NexMap);
                }
            }
            c++;
        }
        
    }
    
    public static string ToStringForList(int[,] map){
        var ret="";
        for(int i=0; i<map.GetLength(0); i++){
            for(int j=0; j<map.GetLength(1); j++){
                ret+=map[i, j];
            }
        }
        return ret;
    }
    
    /*
    AOJ C# compiler is considered old version, so "$" keyword cant use. fuck.
    public static void Print(int[,] map){
        Console.WriteLine(new string(Enumerable.Repeat('-', 10).ToArray()));
        for(int i=0; i<map.GetLength(0); i++){
            for(int j=0; j<map.GetLength(1); j++){
                //Console.Write($"{map[i, j]} ");
            }
            Console.WriteLine();
        }
    }
    */
}

public struct Pos{
    public int X{set; get;}
    public int Y{set; get;}
}

public struct State{
    public int cnt{set; get;}
    public int[,] table{set; get;}
    public Pos GetPos(){
        var retPos = new Pos{X = -1, Y = -1};
        for(int i=0; i<this.table.GetLength(0); i++){
            for(int j=0; j<this.table.GetLength(1); j++){
                if(this.table[i, j]==0){
                    retPos.X = j;
                    retPos.Y = i;
                }
            }
        }
        return retPos;
    }
    
    public State Swap(Pos pre, Pos nex){
        var _tmp = this.table.Clone() as int[,];
        var _cnt = this.cnt;
        _tmp[nex.Y, nex.X] = this.table[pre.Y, pre.X];
        _tmp[pre.Y, pre.X] = this.table[nex.Y, nex.X];
        return new State{cnt = _cnt+=1, table = _tmp};
    }
}

public static class Exclass{
    public static bool ContentEqual<T>(this T[,] array, T[,] other)where T : IComparable
    {
        if(array.GetLength(0)!=other.GetLength(0) || array.GetLength(1)!=other.GetLength(1)) return false;
        for(int i=0; i<array.GetLength(0); i++){
            for(int j=0; j<array.GetLength(1); j++){
                if(array[i, j].CompareTo(other[i, j])!=0) return false;
            }
        }
        return true;
    }
}