How to check if an instance of 8 puzzle is solvable?

03 Nov, 2021
What is 8 puzzle? Given a 3×3 board with 8 tiles (every tile has one number from 1 to 8) and one empty space. The objective is to place the numbers on tiles in order using the empty space. We can slide four adjacent (left, right, above and below) tiles into the empty space
How to find if given state is solvable? Following are two examples, the first example can reach goal state by a series of slides. The second example cannot. 
Following is simple rule to check if a 8 puzzle is solvable. It is not possible to solve an instance of 8 puzzle if number of inversions is odd in the input state. In the examples given in above figure, the first example has 10 inversions, therefore solvable. The second example has 11 inversions, therefore unsolvable.
What is inversion? A pair of tiles form an inversion if the values on tiles are in reverse order of their appearance in goal state. For example, the following instance of 8 puzzle has two inversions, (8, 6) and (8, 7). 
   1   2   3
   4   _   5
   8   6   7      
Following are the implementations to check whether a given instance of 8 puzzle is solvable or not. The idea is simple, we count inversions in the given 8 puzzle. 
C++
Java
Python3
C#
PHP
Javascript
// C++ program to check if a given instance of 8 puzzle is solvable or not#include <iostream>using namespace std; // A utility function to count inversions in given array 'arr[]'int getInvCount(int arr[]){    int inv_count = 0;    for (int i = 0; i < 9 - 1; i++)        for (int j = i+1; j < 9; j++)             // Value 0 is used for empty space             if (arr[j] && arr[i] &&  arr[i] > arr[j])                  inv_count++;    return inv_count;} // This function returns true if given 8 puzzle is solvable.bool isSolvable(int puzzle[3][3]){    // Count inversions in given 8 puzzle    int invCount = getInvCount((int *)puzzle);     // return true if inversion count is even.    return (invCount%2 == 0);} /* Driver program to test above functions */int main(int argv, int** args){  int puzzle[3][3] =  {{1, 8, 2},                      {0, 4, 3},  // Value 0 is used for empty space                      {7, 6, 5}};  isSolvable(puzzle)? cout << "Solvable":                      cout << "Not Solvable";  return 0;}
// Java program to check if a given// instance of 8 puzzle is solvable or notclass GFG{     // A utility function to count// inversions in given array 'arr[]'static int getInvCount(int[][] arr){    int inv_count = 0;    for (int i = 0; i < 3 - 1; i++)        for (int j = i + 1; j < 3; j++)                     // Value 0 is used for empty space            if (arr[j][i] > 0 &&                            arr[j][i] > arr[i][j])                inv_count++;    return inv_count;} // This function returns true// if given 8 puzzle is solvable.static boolean isSolvable(int[][] puzzle){    // Count inversions in given 8 puzzle    int invCount = getInvCount(puzzle);     // return true if inversion count is even.    return (invCount % 2 == 0);} /* Driver code */public static void main (String[] args){    int[][] puzzle = {{1, 8, 2},{0, 4, 3},{7, 6, 5}};    if(isSolvable(puzzle))        System.out.println("Solvable");    else    System.out.println("Not Solvable");}} // This code is contributed by chandan_jnu
# Python3 program to check if a given# instance of 8 puzzle is solvable or not # A utility function to count# inversions in given array 'arr[]'def getInvCount(arr):    inv_count = 0    empty_value = -1    for i in range(0, 9):        for j in range(i + 1, 9):            if arr[j] != empty_value and arr[i] != empty_value and arr[i] > arr[j]:                inv_count += 1    return inv_count      # This function returns true# if given 8 puzzle is solvable.def isSolvable(puzzle) :     # Count inversions in given 8 puzzle    inv_count = getInvCount([j for sub in puzzle for j in sub])     # return true if inversion count is even.    return (inv_count % 2 == 0)         # Driver codepuzzle = [[8, 1, 2],[-1, 4, 3],[7, 6, 5]]if(isSolvable(puzzle)) :    print("Solvable")else :    print("Not Solvable")         # This code is contributed by vitorhugooli    # Fala meu povo desse Brasil varonil 
// C# program to check if a given// instance of 8 puzzle is solvable or notusing System; class GFG{     // A utility function to count// inversions in given array 'arr[]'static int getInvCount(int[,] arr){    int inv_count = 0;    for (int i = 0; i < 3 - 1; i++)        for (int j = i + 1; j < 3; j++)                     // Value 0 is used for empty space            if (arr[j, i] > 0 && arr[j, i] > arr[i, j])                inv_count++;    return inv_count;} // This function returns true// if given 8 puzzle is solvable.static bool isSolvable(int[,] puzzle){    // Count inversions in given 8 puzzle    int invCount = getInvCount(puzzle);     // return true if inversion count is even.    return (invCount % 2 == 0);} /* Driver code */static void Main(){    int[,] puzzle = new int[3,3]{{1, 8, 2},                            {0, 4, 3}, // Value 0 is used for empty space                            {7, 6, 5}};    if(isSolvable(puzzle))        Console.WriteLine("Solvable");    else       Console.WriteLine("Not Solvable");}} // This code is contributed by chandan_jnu
<?php// PHP program to check if// a given instance of 8// puzzle is solvable or not // A utility function to// count inversions in// given array 'arr[]'function getInvCount($arr){    $inv_count = 0;    for ($i = 0; $i < 9 - 1; $i++)        for ( $j = $i + 1; $j < 9; $j++)                $inv_count++;    return $inv_count;} // This function returns true// if given 8 puzzle is solvable.function isSolvable($puzzle){    // Count inversions in    // given 8 puzzle    $invCount = getInvCount($puzzle);     // return true if    // inversion count is even.    return ($invCount % 2 == 0);} // Driver Code$puzzle = array(array(1, 8, 2),                array(0, 4, 3), // Value 0 is used                array(7, 6, 5));// for empty space                 if(isSolvable($puzzle) == true)            echo "Solvable";        else            echo "Not Solvable";                 // This code is contributed by ajit?>
<script> // JavaScript program to check if a given// instance of 8 puzzle is solvable or not // A utility function to count inversions// in given array 'arr[]'function getInvCount(arr){    let inv_count = 0 ;    for(let i=0;i<2;i++){        for(let j=i+1;j<3;j++){                     // Value 0 is used for empty space            if (arr[j][i] > 0 && arr[j][i] > arr[i][j])                inv_count += 1;        }     }    return inv_count;}// This function returns true// if given 8 puzzle is solvable.function isSolvable(puzzle){    // Count inversions in given 8 puzzle    let invCount = getInvCount(puzzle);    // return true if inversion count is even.    return (invCount % 2 == 0);} // Driver code // Value 0 is used for empty spacepuzzle = [[1, 8, 2],[0, 4, 3],[7, 6, 5]] ;if(isSolvable(puzzle))    document.write("Solvable");else    document.write("Not Solvable");     </script>
Output : 
Solvable
Time Complexity: O(1)
Auxiliary Space: O(1)
Note that the above implementation uses simple algorithm for inversion count. It is done this way for simplicity. The code can be optimized to O(nLogn) using the merge sort based algorithm for inversion count.
How does this work? The idea is based on the fact the parity of inversions remains same after a set of moves, i.e., if the inversion count is odd in initial stage, then it remain odd after any sequence of moves and if the inversion count is even, then it remains even after any sequence of moves. In the goal state, there are 0 inversions. So we can reach goal state only from a state which has even inversion count.How parity of inversion count is invariant? When we slide a tile, we either make a row move (moving a left or right tile into the blank space), or make a column move (moving a up or down tile to the blank space). 
a) A row move doesn’t change the inversion count. See following example  
   1   2   3    Row Move     1   2   3
   4   _   5   ---------->   _   4   5 
   8   6   7                 8   6   7
  Inversion count remains 2 after the move

   1   2   3    Row Move     1   2   3
   4   _   5   ---------->   4   5   _
   8   6   7                 8   6   7
  Inversion count remains 2 after the move
b) A column move does one of the following three. .....(i) Increases inversion count by 2. See following example. 
         1   2   3   Column Move     1   _   3
         4   _   5   ----------->    4   2   5  
         8   6   7                   8   6   7
      Inversion count increases by 2 (changes from 2 to 4)
       
.....(ii) Decreases inversion count by 2
         1   3   4    Column Move     1   3   4
         5   _   6   ------------>    5   2   6
         7   2   8                    7   _   8
      Inversion count decreases by 2 (changes from 5  to 3)
.....(iii) Keeps the inversion count same. 
         1   2   3    Column Move     1   2   3
         4   _   5   ------------>    4   6   5
         7   6   8                    7   _   8
        Inversion count remains 1 after the move 
So if a move either increases/decreases inversion count by 2, or keeps the inversion count same, then it is not possible to change parity of a state by any sequence of row/column moves.
Exercise: How to check if a given instance of 15 puzzle is solvable or not. In a 15 puzzle, we have 4×4 board where 15 tiles have a number and one empty space. Note that the above simple rules of inversion count don’t directly work for 15 puzzle, the rules need to be modified for 15 puzzle.
Related Article: How to check if an instance of 15 puzzle is solvable?This article is contributed by Ishan. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above 
jit_t
Chandan_Kumar
vibhu4agarwal
Akanksha_Rai
lukijosai
divyeshrabadiya07
rohan07
kk9826225
vho2009
subham348
Mathematical
Mathematical
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Merge two sorted arrays
Operators in C / C++
Prime Numbers
Find minimum number of coins that make a given value
Minimum number of jumps to reach end
Algorithm to solve Rubik's Cube
Modulo 10^9+7 (1000000007)
The Knight's tour problem | Backtracking-1
Modulo Operator (%) in C/C++ with Examples
Program for factorial of a number