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: Time Limit Exceeded)

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

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



public class EightPuzzle
{
    public static void Main()
    {
        var inputs = Console.ReadLine().Split(' ').Select(int.Parse)
            .Concat(Console.ReadLine().Split(' ').Select(int.Parse))
            .Concat(Console.ReadLine().Split(' ').Select(int.Parse))
            .Cast<int>()
            .ToArray();
        
        var board = new Board(inputs);
        
        var max = 1;
        while (board.Move(max) == -1)
        {
            board = new Board(inputs);
            max++;
        }
        
        Console.WriteLine(max);
    }
}

public class Board
{
    public Node[] Nodes { get; set; }
    private int MoveCount { get; set; }
    
    public Board(IEnumerable<int> inputs)
    {
        Nodes = inputs.Select((x, i) => new Node((i + 1) % 9, x))
            .ToArray();
        MoveCount = 0;
    }
    
    public Board() { }
    
    public int Move(int max)
    {
        MoveCount++;
        
        var empty = Nodes.First(x => x.Current == 0);
        var children = empty.AdjacentNumbers
            .Select(_ => Board.Clone(this))
            .ToArray();
        
        empty.AdjacentNumbers
            .Select((adj, i) => 
            {
                var board = children[i];
                var left = board.Nodes.First(x => x.Current == 0);
                var right = board.Nodes.First(x => x.CorrectNumber == adj);
                
                if (left.LastNumber == right.Current)
                {
                    children[i] = null;
                    return 0;
                }
                return board.SwapNode(left, right);
            })
            .ToArray();
        
        if (children.Where(x => x != null).Any(x => x.Nodes.All(node => node.IsCorrect())))
        {
            return MoveCount;
        }
        
        if (MoveCount == max)
            return -1;
        
        return children.Where(x => x != null)
            .Select(x => x.Move(max))
            .Where(x => x != -1)
            .DefaultIfEmpty(-1)
            .Min();
    }
    
    public int SwapNode(Node left, Node right)
    {
        left.LastNumber = left.Current;
        right.LastNumber = right.Current;

        left.Current = right.LastNumber;
        right.Current = left.LastNumber;
        return 0; // dummy
    }
    
    private static Board Clone(Board board)
    {
        return new Board
        {
            Nodes = board.Nodes.Select(Node.Clone)
                .ToArray(),
            MoveCount = board.MoveCount
        };
    }

    public override string ToString()
    {
        return Nodes.Select(x => x.Current)
            .Select(x => x.ToString())
            .Aggregate((acc, x) => acc + " " + x);
    }
}

public class Node
{
    private static Dictionary<int, int[]> adjacentNumbersDic =
        new Dictionary<int, int[]>
        {
            { 1, new [] { 2, 4 } },
            { 2, new [] { 1, 3, 5 } },
            { 3, new [] { 2, 6 } },
            { 4, new [] { 1, 5, 7 } },
            { 5, new [] { 2, 4, 6, 8 } },
            { 6, new [] { 3, 5, 0 } },
            { 7, new [] { 4, 8 } },
            { 8, new [] { 5, 7, 0 } },
            { 0, new [] { 6, 8 } },
        };

    public int CorrectNumber { get; private set; }    
    public int Current { get; set; }
    public int LastNumber { get; set; }
    public int[] AdjacentNumbers { get { return adjacentNumbersDic[CorrectNumber]; } }

    public Node(int correct, int current, int lastNumber = -1)
    {
        CorrectNumber = correct;
        Current = current;
        LastNumber = lastNumber;
    }
    
    public static Node Clone(Node node)
    {
        return new Node(node.CorrectNumber, node.Current, node.LastNumber);
    }
    
    public bool IsCorrect() { return CorrectNumber == Current; }
}