Open In App

Solving Sudoku using Bitwise Algorithm

Improve
Improve
Like Article
Like
Save
Share
Report

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.

CPP
#include <iostream>
#include <cstring> // for memset

#define N 9

using namespace std;

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; 
    }  
}

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][c] == 0) {
        for (int i = 1; i <= 9; i++)
        {
            int digit = 1 << (i - 1);
            
            if (!((submatrixDigits[r / 3][c / 3] & digit) 
                  || (rowDigits[r] & digit) 
                  || (columnDigits[c] & digit)))
            {
                submatrixDigits[r / 3][c / 3] |= digit;
                rowDigits[r] |= digit;
                columnDigits[c] |= digit;
                board[r][c] = i;
                
                if (solve(r, c + 1, board, submatrixDigits, rowDigits, columnDigits))
                    return true;
                else
                {
                    submatrixDigits[r / 3][c / 3] &= ~digit;
                    rowDigits[r] &= ~digit;
                    columnDigits[c] &= ~digit;
                    board[r][c] = 0;
                }
            }
        }
        return false;
    }
    return solve(r, c + 1, board, submatrixDigits, rowDigits, columnDigits);
}

bool SolveSudoku(int board[9][9])
{
    int submatrixDigits[3][3];
    int columnDigits[9];
    int rowDigits[9];
    
    memset(submatrixDigits, 0, sizeof(submatrixDigits));
    memset(rowDigits, 0, sizeof(rowDigits));
    memset(columnDigits, 0, sizeof(columnDigits));
    
    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;
            }
    
    if (solve(0, 0, board, submatrixDigits, rowDigits, columnDigits))
        return true;
    else
        return false;
}

int main()  
{  
    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;  
}
Java
import java.util.Arrays;

public class SudokuSolver {

    // N is used for the size of the Sudoku grid. Size will
    // be NxN
    private static final int N = 9;

    // A utility function to print the grid
    private static void printGrid(int[][] grid)
    {
        for (int row = 0; row < N; row++) {
            for (int col = 0; col < N; col++) {
                System.out.print(grid[row][col] + " ");
            }
            System.out.println();
        }
    }

    // Takes a partially filled-in grid and attempts to
    // assign values to all unassigned locations to meet the
    // requirements for Sudoku solution
    private static boolean solve(int r, int c,
                                 int[][] board,
                                 int[][] submatrixDigits,
                                 int[] rowDigits,
                                 int[] columnDigits)
    {
        if (r == 9) {
            return true;
        }
        if (c == 9) {
            return solve(r + 1, 0, board, submatrixDigits,
                         rowDigits, columnDigits);
        }

        if (board[r][c] == 0) {
            for (int i = 1; i <= 9; i++) {
                int digit = 1 << (i - 1);

                if ((submatrixDigits[r / 3][c / 3] & digit)
                        == 0
                    && (rowDigits[r] & digit) == 0
                    && (columnDigits[c] & digit) == 0) {
                    // Set digit
                    submatrixDigits[r / 3][c / 3] |= digit;
                    rowDigits[r] |= digit;
                    columnDigits[c] |= digit;
                    board[r][c] = i;

                    if (solve(r, c + 1, board,
                              submatrixDigits, rowDigits,
                              columnDigits)) {
                        return true;
                    }
                    else {
                        submatrixDigits[r / 3][c / 3]
                            &= ~digit;
                        rowDigits[r] &= ~digit;
                        columnDigits[c] &= ~digit;
                        board[r][c] = 0;
                    }
                }
            }
            return false;
        }
        return solve(r, c + 1, board, submatrixDigits,
                     rowDigits, columnDigits);
    }

    // Function checks if Sudoku can be solved or not
    private static boolean solveSudoku(int[][] board)
    {
        int[][] submatrixDigits = new int[3][3];
        int[] columnDigits = new int[9];
        int[] rowDigits = new int[9];

        Arrays.fill(columnDigits, 0);
        Arrays.fill(rowDigits, 0);

        // 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
        return solve(0, 0, board, submatrixDigits,
                     rowDigits, columnDigits);
    }

    // Driver Code
    public static void main(String[] args)
    {
        // 0 means unassigned cells
        int[][] grid = { { 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)) {
            printGrid(grid);
        }
        else {
            System.out.println("No solution exists");
        }
    }
}
JavaScript
// Function to print the Sudoku grid
function printGrid(grid) {
    for (let row = 0; row < N; row++) {
        let rowStr = '';
        for (let col = 0; col < N; col++) {
            rowStr += grid[row][col] + ' ';
        }
        console.log(rowStr);
    }
}

// Function to solve Sudoku recursively
function solve(r, c, board, submatrixDigits, rowDigits, columnDigits) {
    // Base case: If all rows are filled, the Sudoku is solved
    if (r === 9) {
        return true;
    }
    // If a row is filled, move to the next row
    if (c === 9) {
        return solve(r + 1, 0, board, submatrixDigits, rowDigits, columnDigits);
    }
    // If the cell is empty
    if (board[r][c] === 0) {
        for (let i = 1; i <= 9; i++) {
            const digit = 1 << (i - 1);
            // Check if the digit is not present in the same row, column, or submatrix
            if (!(submatrixDigits[Math.floor(r / 3)][Math.floor(c / 3)] & digit)
                && !(rowDigits[r] & digit)
                && !(columnDigits[c] & digit)) {
                // Set the digit and continue solving
                submatrixDigits[Math.floor(r / 3)][Math.floor(c / 3)] |= digit;
                rowDigits[r] |= digit;
                columnDigits[c] |= digit;
                board[r][c] = i;
                if (solve(r, c + 1, board, submatrixDigits, rowDigits, columnDigits)) {
                    return true;
                } else {
                    // Backtrack if the digit doesn't lead to a solution
                    submatrixDigits[Math.floor(r / 3)][Math.floor(c / 3)] &= ~digit;
                    rowDigits[r] &= ~digit;
                    columnDigits[c] &= ~digit;
                    board[r][c] = 0;
                }
            }
        }
        return false;
    }
    // If the cell is already filled, move to the next cell
    return solve(r, c + 1, board, submatrixDigits, rowDigits, columnDigits);
}

// Function to check if Sudoku can be solved
function solveSudoku(board) {
    // Initialize arrays to track digits in submatrices, rows, and columns
    const submatrixDigits = Array.from({ length: 3 }, () => Array(3).fill(0));
    const rowDigits = new Array(9).fill(0);
    const columnDigits = new Array(9).fill(0);

    // Populate the arrays with initial Sudoku values
    for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
            if (board[i][j] > 0) {
                const value = 1 << (board[i][j] - 1);
                submatrixDigits[Math.floor(i / 3)][Math.floor(j / 3)] |= value;
                rowDigits[i] |= value;
                columnDigits[j] |= value;
            }
        }
    }

    // Start solving Sudoku using backtracking
    if (solve(0, 0, board, submatrixDigits, rowDigits, columnDigits)) {
        return true; // Sudoku solved successfully
    } else {
        return false; // No solution exists
    }
}

// Define the Sudoku grid
const N = 9;
const grid = [
    [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]
];

// Solve the Sudoku
if (solveSudoku(grid)) {
    // Print the solved Sudoku grid
    printGrid(grid);
} else {
    console.log("No solution exists");
}
Python3
# Python program to solve sudoku

# N is used for the size of Sudoku grid.  
# Size will be NxN  
N = 9

# A utility function to print grid 
def printGrid(grid):  
    for row in range(N):  
        for col in range(N):  
            print(grid[row][col], end = " ");  
        print(); 

# 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) 
def solve(r, c, board, submatrixDigits, rowDigits, columnDigits):
    if r == 9:
        return True
    if c == 9:
        return solve(r + 1, 0, board, submatrixDigits, rowDigits, columnDigits)
    
    if board[r][c] == 0:
        for i in range(1, 10):
            digit = 1 << (i - 1)
            
            if not ((submatrixDigits[r // 3][c // 3] & digit) 
                  or (rowDigits[r] & digit) 
                  or (columnDigits[c] & digit)):
                # set digit
                submatrixDigits[r // 3][c // 3] |= digit
                rowDigits[r] |= digit
                columnDigits[c] |= digit
                board[r][c] = i
                
                if solve(r, c + 1, board, submatrixDigits, rowDigits, columnDigits):
                    return True
                else:
                    submatrixDigits[r // 3][c // 3] &= ~digit
                    rowDigits[r] &= ~digit
                    columnDigits[c] &= ~digit
                    board[r][c] = 0
        return False
    return solve(r, c + 1, board, submatrixDigits, rowDigits, columnDigits)

# Function checks if Sudoku can be
# solved or not
def SolveSudoku(board):
    submatrixDigits = [[0]*3 for _ in range(3)]
    columnDigits = [0]*9
    rowDigits = [0]*9
    
    # get 3x3 submatrix, row and column digits
    for i in range(9):
        for j in range(9):
            if board[i][j] > 0:
                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 
if __name__ == "__main__":
    # 0 means unassigned cells  
    grid = [[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:
        print("No solution exists")

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








Last Updated : 26 Mar, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads