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

# frozen_string_literal: true
require 'set'

checked_puzzles = Set.new
current_puzzles = Set.new

input_puzzle = 3.times.map{gets.split.map(&:to_i)}.flatten
current_puzzles.add(input_puzzle)
count = 0

goal_puzzle = [1, 2, 3, 4, 5, 6, 7, 8, 0]

loop do
  next_puzzles = Set.new
  current_puzzles.each do |puzzle|
    if puzzle == goal_puzzle
      puts count
      exit
    end

    zero_point = puzzle.index(0)
    y, x = zero_point.divmod(3)
    if x != 2
      tmp_puzzle = puzzle.dup
      tmp_puzzle[zero_point] = puzzle[zero_point + 1]
      tmp_puzzle[zero_point + 1] = 0
      next_puzzles.add(tmp_puzzle)
    end
    if x != 0
      tmp_puzzle = puzzle.dup
      tmp_puzzle[zero_point] = puzzle[zero_point - 1]
      tmp_puzzle[zero_point - 1] = 0
      next_puzzles.add(tmp_puzzle)
    end
    if y != 2
      tmp_puzzle = puzzle.dup
      tmp_puzzle[zero_point] = puzzle[zero_point + 3]
      tmp_puzzle[zero_point + 3] = 0
      next_puzzles.add(tmp_puzzle)
    end
    if y != 0
      tmp_puzzle = puzzle.dup
      tmp_puzzle[zero_point] = puzzle[zero_point - 3]
      tmp_puzzle[zero_point - 3] = 0
      next_puzzles.add(tmp_puzzle)
    end
  end
  checked_puzzles.merge(current_puzzles)
  current_puzzles = next_puzzles - checked_puzzles
  count += 1
end