Solving Sudoku using Bitwise Algorithm


Given a partially filled 9×9 matrix, digits (from 1 to 9) must be assigned to the empty cells so that every row, column, and submatrix of size 3×3 contains exactly one instance of the digits from 1 to 9.

The Pure backtracking solution for this problem is described here. It is strongly recommended that the reader know how the pure backtracking solution works before move on.

In the pure backtracking solution, we iterate through the matrix and whenever an empty cell (cell without any digit) is found, we assign a digit to the cell, where such digit is not present in the current column, row, and 3×3 submatrix. After assigning the digit to the current cell, we recursively check whether this assignment leads to a valid solution or not. If the assignment doesn’t lead to a valid solution, then we try the next valid digit for the current empty cell. And if none of the digits leads to a valid solution, then the instance is infeasible.



1. If there is no empty cell in the matrix M:
    return true
2. Let (i, j) be an empty cell in the matrix M
3. For i from 1 to 9:
    3.1. If i is not present in the row r, in column c, and the 3x3
    submatrix of (r, c):
        a) M(r, c) = i 
        b) recursively try fill in remaining empty cells
        c) If recursion was successful:
            return true
        d) M(r, c) = 0
4. return false
  • The step (3.1) can be performed by traversing the respective row, column, and 3×3 submatrix. However, we can make this step faster by preprocessing those digits before the backtracking, and this is the main point of this article. So, let’s consider the matrix below as an example:

    We can keep track of the digits of a row, column, and 3×3 submatrix in the bits of an integer, for example, consider the first row of the previous matrix, we can store those digits in the following way:

    bits order - 9 8 7 6 5 4 3 2 1
    bits       - 0 0 1 0 1 0 1 0 0
    

    And then at the step (3.1), we can use bitwise operations to determine if the digit i is in the row, column and 3×3 submatrix. Let rowDigits[r] be the integer that contains the digits of row r, then we can check if digit i is in row r with the following expression:

    rowsDigits[r] & (1<<(i - 1))
    

    If the expression above is equals to 0 then the digit i is not present in row r. For example, if r = 0, and i = 1, then:

    bits order                - 9 8 7 6 5 4 3 2 1
    rowDigits[r]              - 0 0 1 0 1 0 1 0 0
    1<<(i - 1)                - 0 0 0 0 0 0 0 0 1
    rowDigits[r]&(1<<(i - 1)) - 0 0 0 0 0 0 0 0 0
    
  • Once the condition of step (3.1) is true, the step (3.1a) is executed, and then we need to insert the digit i in rowDigits, columnDigits, and subMatrixDigits, we can do this with the following expression:

    rowsDigits[r] | (1<<(i - 1))
    

    For example, if r = 0, and i = 1, then:

    bits order                - 9 8 7 6 5 4 3 2 1
    rowDigits[r]              - 0 0 1 0 1 0 1 0 0
    1<<(i - 1)                - 0 0 0 0 0 0 0 0 1
    rowDigits[r]|(1<<(i - 1)) - 0 0 1 0 1 0 1 0 1
    
  • In the case where the condition of step (3.1c) is false, the step (3.1d) is executed, and then we need to remove the digit i from rowDigits, columnDigits, and subMatrixDigits, we can do this with the following expression:

    rowsDigits[r] & ~(1<<(i - 1))
    

    For example, if r = 0, and i = 1, then:

    bits order                - 9 8 7 6 5 4 3 2 1
    rowDigits[r]              - 0 0 1 0 1 0 1 0 0
    1<<(i - 1)                - 0 0 0 0 0 0 0 0 1
    ~(1<<(i - 1))             - 1 1 1 1 1 1 1 1 0
    rowDigits[r]&~(1<<(i - 1) - 0 0 1 0 1 0 1 0 0
    

Below is the implementation of the above approach.

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to solve sudoku
#include <iostream>
#include <string.h>
  
// N is used for the size of Sudoku grid.  
// Size will be NxN  
#define N 9
  
using namespace std;
  
/* A utility function to print grid */
void printGrid(int grid[N][N])  
{  
    for (int row = 0; row < N; row++)  
    {  
    for (int col = 0; col < N; col++)  
            cout << grid[row][col] << " ";  
        cout << endl; 
    }  
}
/* Takes a partially filled-in grid and attempts  
to assign values to all unassigned locations in  
such a way to meet the requirements for 
Sudoku solution (non-duplication across rows, 
columns, and boxes) */
bool solve(int r, int c, int board[9][9], 
           int submatrixDigits[3][3], 
           int rowDigits[9], 
           int columnDigits[9])
{
    if (r == 9)
    {
          
        return true;
    }
    if (c == 9)
    {
        return solve(r + 1, 0, board, submatrixDigits, 
                     rowDigits, columnDigits);
    }
      
    if (board[r] == 0) {
        for (int i = 1; i <= 9; i++)
        {
            int digit = 1 << (i - 1);
              
            if (!((submatrixDigits[r / 3] & digit) 
                  || (rowDigits[r] & digit) 
                  || (columnDigits & digit)))
            {
                // set digit
                submatrixDigits[r / 3] |= digit;
                rowDigits[r] |= digit;
                columnDigits |= digit;
                board[r] = i;
                  
                if (solve(r, c + 1, board, submatrixDigits,
                          rowDigits, columnDigits))
                {
                    return true;
                }
                else
                {
                    submatrixDigits[r / 3] &= ~digit;
                    rowDigits[r] &= ~digit;
                    columnDigits &= ~digit;
                    board[r] = 0;
                }
            }
        }
        return false;
    }
    return solve(r, c + 1, board, submatrixDigits, 
                 rowDigits, columnDigits);
}
  
// Function checks if Sudoku can be
// solved or not
bool SolveSudoku(int board[9][9])
{
    int submatrixDigits[3][3];
    int columnDigits[9];
    int rowDigits[9];
      
    for (int i = 0; i < 3; i++)
        memset(submatrixDigits[i], 0, 3 * sizeof(int));
      
      
    memset(rowDigits, 0, 9 * sizeof(int));
    memset(columnDigits, 0, 9 * sizeof(int));
      
    // get 3x3 submatrix, row and column digits
    for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9; j++)
            if (board[i][j] > 0)
            {
                int value = 1 << (board[i][j] - '1');
                submatrixDigits[i / 3][j / 3] |= value;
                rowDigits[i] |= value;
                columnDigits[j] |= value;
            }
    // Backtrack
    if (solve(0, 0, board, submatrixDigits,
              rowDigits, columnDigits))
        return true;
    else
        return false;
}
  
  
// Driver Code 
int main()  
{  
    // 0 means unassigned cells  
    int grid[N][N] = {{3, 0, 6, 5, 0, 8, 4, 0, 0},  
                      {5, 2, 0, 0, 0, 0, 0, 0, 0},  
                      {0, 8, 7, 0, 0, 0, 0, 3, 1},  
                      {0, 0, 3, 0, 1, 0, 0, 8, 0},  
                      {9, 0, 0, 8, 6, 3, 0, 0, 5},  
                      {0, 5, 0, 0, 9, 0, 6, 0, 0},  
                      {1, 3, 0, 0, 0, 0, 2, 5, 0},  
                      {0, 0, 0, 0, 0, 0, 0, 7, 4},  
                      {0, 0, 5, 2, 0, 6, 3, 0, 0}};  
    if (SolveSudoku(grid) == true)  
        printGrid(grid);  
    else
        cout << "No solution exists";  
    
    return 0;  
}  

chevron_right


Output:

3 1 6 5 2 8 4 3 4 
5 2 2 1 3 4 5 6 7 
3 8 7 5 6 7 1 3 1 
1 2 3 3 1 5 4 8 6 
9 3 4 8 6 3 2 1 5 
5 5 6 2 9 1 6 7 3 
1 3 1 4 5 2 2 5 8 
2 4 3 6 1 8 7 7 4 
6 5 5 2 7 6 3 2 1

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up


If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.