Algorithm to Solve Sudoku | Sudoku Solver
Given a partially filled 9×9 2D array ‘grid[9][9]’, the goal is to assign digits (from 1 to 9) to the empty cells so that every row, column, and subgrid of size 3×3 contains exactly one instance of the digits from 1 to 9.
Examples:
Input: 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} }
Output:
3 1 6 5 7 8 4 9 2
5 2 9 1 3 4 7 6 8
4 8 7 6 2 9 5 3 1
2 6 3 4 1 5 9 8 7
9 7 4 8 6 3 1 2 5
8 5 1 7 9 2 6 4 3
1 3 8 9 4 7 2 5 6
6 9 2 3 5 1 8 7 4
7 4 5 2 8 6 3 1 9
Explanation: Each row, column and 3*3 box of the output matrix contains unique numbers.Input: grid
{ { 3, 1, 6, 5, 7, 8, 4, 9, 2 },
{ 5, 2, 9, 1, 3, 4, 7, 6, 8 },
{ 4, 8, 7, 6, 2, 9, 5, 3, 1 },
{ 2, 6, 3, 0, 1, 5, 9, 8, 7 },
{ 9, 7, 4, 8, 6, 0, 1, 2, 5 },
{ 8, 5, 1, 7, 9, 2, 6, 4, 3 },
{ 1, 3, 8, 0, 4, 7, 2, 0, 6 },
{ 6, 9, 2, 3, 5, 1, 8, 7, 4 },
{ 7, 4, 5, 0, 8, 6, 3, 1, 0 } };
Output:
3 1 6 5 7 8 4 9 2
5 2 9 1 3 4 7 6 8
4 8 7 6 2 9 5 3 1
2 6 3 4 1 5 9 8 7
9 7 4 8 6 3 1 2 5
8 5 1 7 9 2 6 4 3
1 3 8 9 4 7 2 5 6
6 9 2 3 5 1 8 7 4
7 4 5 2 8 6 3 1 9
Explanation: Each row, column and 3*3 box of the output matrix contains unique numbers.
Naive Approach:
The naive approach is to generate all possible configurations of numbers from 1 to 9 to fill the empty cells. Try every configuration one by one until the correct configuration is found, i.e. for every unassigned position fill the position with a number from 1 to 9. After filling all the unassigned positions check if the matrix is safe or not. If safe print else recurs for other cases.
Follow the steps below to solve the problem:
- Create a function that checks if the given matrix is valid sudoku or not. Keep Hashmap for the row, column and boxes. If any number has a frequency greater than 1 in the hashMap return false else return true;
- Create a recursive function that takes a grid and the current row and column index.
- Check some base cases.
- If the index is at the end of the matrix, i.e. i=N-1 and j=N then check if the grid is safe or not, if safe print the grid and return true else return false.
- The other base case is when the value of column is N, i.e j = N, then move to next row, i.e. i++ and j = 0.
- If the current index is not assigned then fill the element from 1 to 9 and recur for all 9 cases with the index of next element, i.e. i, j+1. if the recursive call returns true then break the loop and return true.
- If the current index is assigned then call the recursive function with the index of the next element, i.e. i, j+1
Below is the implementation of the above approach:
C++
#include <iostream> using namespace std; // N is the size of the 2D matrix N*N #define N 9 /* A utility function to print grid */ void print( int arr[N][N]) { for ( int i = 0; i < N; i++) { for ( int j = 0; j < N; j++) cout << arr[i][j] << " " ; cout << endl; } } // Checks whether it will be // legal to assign num to the // given row, col bool isSafe( int grid[N][N], int row, int col, int num) { // Check if we find the same num // in the similar row , we // return false for ( int x = 0; x <= 8; x++) if (grid[row][x] == num) return false ; // Check if we find the same num in // the similar column , we // return false for ( int x = 0; x <= 8; x++) if (grid[x][col] == num) return false ; // Check if we find the same num in // the particular 3*3 matrix, // we return false int startRow = row - row % 3, startCol = col - col % 3; for ( int i = 0; i < 3; i++) for ( int j = 0; j < 3; j++) if (grid[i + startRow][j + startCol] == num) return false ; return true ; } /* 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 solveSudoku( int grid[N][N], int row, int col) { // Check if we have reached the 8th // row and 9th column (0 // indexed matrix) , we are // returning true to avoid // further backtracking if (row == N - 1 && col == N) return true ; // Check if column value becomes 9 , // we move to next row and // column start from 0 if (col == N) { row++; col = 0; } // Check if the current position of // the grid already contains // value >0, we iterate for next column if (grid[row][col] > 0) return solveSudoku(grid, row, col + 1); for ( int num = 1; num <= N; num++) { // Check if it is safe to place // the num (1-9) in the // given row ,col ->we // move to next column if (isSafe(grid, row, col, num)) { /* Assigning the num in the current (row,col) position of the grid and assuming our assigned num in the position is correct */ grid[row][col] = num; // Checking for next possibility with next // column if (solveSudoku(grid, row, col + 1)) return true ; } // Removing the assigned num , // since our assumption // was wrong , and we go for // next assumption with // diff num value grid[row][col] = 0; } 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, 0, 0)) print(grid); else cout << "no solution exists " << endl; return 0; // This is code is contributed by Pradeep Mondal P } |
C
#include <stdio.h> #include <stdlib.h> // N is the size of the 2D matrix N*N #define N 9 /* A utility function to print grid */ void print( int arr[N][N]) { for ( int i = 0; i < N; i++) { for ( int j = 0; j < N; j++) printf ( "%d " ,arr[i][j]); printf ( "\n" ); } } // Checks whether it will be legal // to assign num to the // given row, col int isSafe( int grid[N][N], int row, int col, int num) { // Check if we find the same num // in the similar row , we return 0 for ( int x = 0; x <= 8; x++) if (grid[row][x] == num) return 0; // Check if we find the same num in the // similar column , we return 0 for ( int x = 0; x <= 8; x++) if (grid[x][col] == num) return 0; // Check if we find the same num in the // particular 3*3 matrix, we return 0 int startRow = row - row % 3, startCol = col - col % 3; for ( int i = 0; i < 3; i++) for ( int j = 0; j < 3; j++) if (grid[i + startRow][j + startCol] == num) return 0; return 1; } /* 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) */ int solveSudoku( int grid[N][N], int row, int col) { // Check if we have reached the 8th row // and 9th column (0 // indexed matrix) , we are // returning true to avoid // further backtracking if (row == N - 1 && col == N) return 1; // Check if column value becomes 9 , // we move to next row and // column start from 0 if (col == N) { row++; col = 0; } // Check if the current position // of the grid already contains // value >0, we iterate for next column if (grid[row][col] > 0) return solveSudoku(grid, row, col + 1); for ( int num = 1; num <= N; num++) { // Check if it is safe to place // the num (1-9) in the // given row ,col ->we move to next column if (isSafe(grid, row, col, num)==1) { /* assigning the num in the current (row,col) position of the grid and assuming our assigned num in the position is correct */ grid[row][col] = num; // Checking for next possibility with next // column if (solveSudoku(grid, row, col + 1)==1) return 1; } // Removing the assigned num , // since our assumption // was wrong , and we go for next // assumption with // diff num value grid[row][col] = 0; } return 0; } 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, 0, 0)==1) print(grid); else printf ( "No solution exists" ); return 0; // This is code is contributed by Pradeep Mondal P } |
Java
// Java program for above approach public class Sudoku { // N is the size of the 2D matrix N*N static int N = 9 ; /* 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) */ static boolean solveSudoku( int grid[][], int row, int col) { /*if we have reached the 8th row and 9th column (0 indexed matrix) , we are returning true to avoid further backtracking */ if (row == N - 1 && col == N) return true ; // Check if column value becomes 9 , // we move to next row // and column start from 0 if (col == N) { row++; col = 0 ; } // Check if the current position // of the grid already // contains value >0, we iterate // for next column if (grid[row][col] != 0 ) return solveSudoku(grid, row, col + 1 ); for ( int num = 1 ; num < 10 ; num++) { // Check if it is safe to place // the num (1-9) in the // given row ,col ->we move to next column if (isSafe(grid, row, col, num)) { /* assigning the num in the current (row,col) position of the grid and assuming our assigned num in the position is correct */ grid[row][col] = num; // Checking for next // possibility with next column if (solveSudoku(grid, row, col + 1 )) return true ; } /* removing the assigned num , since our assumption was wrong , and we go for next assumption with diff num value */ grid[row][col] = 0 ; } return false ; } /* A utility function to print grid */ static void print( int [][] grid) { for ( int i = 0 ; i < N; i++) { for ( int j = 0 ; j < N; j++) System.out.print(grid[i][j] + " " ); System.out.println(); } } // Check whether it will be legal // to assign num to the // given row, col static boolean isSafe( int [][] grid, int row, int col, int num) { // Check if we find the same num // in the similar row , we // return false for ( int x = 0 ; x <= 8 ; x++) if (grid[row][x] == num) return false ; // Check if we find the same num // in the similar column , // we return false for ( int x = 0 ; x <= 8 ; x++) if (grid[x][col] == num) return false ; // Check if we find the same num // in the particular 3*3 // matrix, we return false int startRow = row - row % 3 , startCol = col - col % 3 ; for ( int i = 0 ; i < 3 ; i++) for ( int j = 0 ; j < 3 ; j++) if (grid[i + startRow][j + startCol] == num) return false ; return true ; } // Driver Code public static void main(String[] args) { 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, 0 , 0 )) print(grid); else System.out.println( "No Solution exists" ); } // This is code is contributed by Pradeep Mondal P } |
Python3
# N is the size of the 2D matrix N*N N = 9 # A utility function to print grid def printing(arr): for i in range (N): for j in range (N): print (arr[i][j], end = " " ) print () # Checks whether it will be # legal to assign num to the # given row, col def isSafe(grid, row, col, num): # Check if we find the same num # in the similar row , we # return false for x in range ( 9 ): if grid[row][x] = = num: return False # Check if we find the same num in # the similar column , we # return false for x in range ( 9 ): if grid[x][col] = = num: return False # Check if we find the same num in # the particular 3*3 matrix, # we return false startRow = row - row % 3 startCol = col - col % 3 for i in range ( 3 ): for j in range ( 3 ): if grid[i + startRow][j + startCol] = = num: return False return True # 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 solveSudoku(grid, row, col): # Check if we have reached the 8th # row and 9th column (0 # indexed matrix) , we are # returning true to avoid # further backtracking if (row = = N - 1 and col = = N): return True # Check if column value becomes 9 , # we move to next row and # column start from 0 if col = = N: row + = 1 col = 0 # Check if the current position of # the grid already contains # value >0, we iterate for next column if grid[row][col] > 0 : return solveSudoku(grid, row, col + 1 ) for num in range ( 1 , N + 1 , 1 ): # Check if it is safe to place # the num (1-9) in the # given row ,col ->we # move to next column if isSafe(grid, row, col, num): # Assigning the num in # the current (row,col) # position of the grid # and assuming our assigned # num in the position # is correct grid[row][col] = num # Checking for next possibility with next # column if solveSudoku(grid, row, col + 1 ): return True # Removing the assigned num , # since our assumption # was wrong , and we go for # next assumption with # diff num value grid[row][col] = 0 return False # Driver Code # 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, 0 , 0 )): printing(grid) else : print ( "no solution exists " ) # This code is contributed by sudhanshgupta2019a |
C#
// C# program for above approach using System; class GFG { // N is the size of the 2D matrix N*N static int N = 9; /* 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) */ static bool solveSudoku( int [,] grid, int row, int col) { /*if we have reached the 8th row and 9th column (0 indexed matrix) , we are returning true to avoid further backtracking */ if (row == N - 1 && col == N) return true ; // Check if column value becomes 9 , // we move to next row // and column start from 0 if (col == N) { row++; col = 0; } // Check if the current position // of the grid already // contains value >0, we iterate // for next column if (grid[row,col] != 0) return solveSudoku(grid, row, col + 1); for ( int num = 1; num < 10; num++) { // Check if it is safe to place // the num (1-9) in the // given row ,col ->we move to next column if (isSafe(grid, row, col, num)) { /* assigning the num in the current (row,col) position of the grid and assuming our assigned num in the position is correct */ grid[row,col] = num; // Checking for next // possibility with next column if (solveSudoku(grid, row, col + 1)) return true ; } /* removing the assigned num , since our assumption was wrong , and we go for next assumption with diff num value */ grid[row,col] = 0; } return false ; } /* A utility function to print grid */ static void print( int [,] grid) { for ( int i = 0; i < N; i++) { for ( int j = 0; j < N; j++) Console.Write(grid[i,j] + " " ); Console.WriteLine(); } } // Check whether it will be legal // to assign num to the // given row, col static bool isSafe( int [,] grid, int row, int col, int num) { // Check if we find the same num // in the similar row , we // return false for ( int x = 0; x <= 8; x++) if (grid[row,x] == num) return false ; // Check if we find the same num // in the similar column , // we return false for ( int x = 0; x <= 8; x++) if (grid[x,col] == num) return false ; // Check if we find the same num // in the particular 3*3 // matrix, we return false int startRow = row - row % 3, startCol = col - col % 3; for ( int i = 0; i < 3; i++) for ( int j = 0; j < 3; j++) if (grid[i + startRow,j + startCol] == num) return false ; return true ; } // Driver code static void Main() { 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, 0, 0)) print(grid); else Console.WriteLine( "No Solution exists" ); } } // This code is contributed by divyesh072019. |
Javascript
<script> // Javascript program for above approach // N is the size of the 2D matrix N*N let N = 9; /* 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) */ function solveSudoku(grid, row, col) { /* If we have reached the 8th row and 9th column (0 indexed matrix) , we are returning true to avoid further backtracking */ if (row == N - 1 && col == N) return true ; // Check if column value becomes 9 , // we move to next row // and column start from 0 if (col == N) { row++; col = 0; } // Check if the current position // of the grid already // contains value >0, we iterate // for next column if (grid[row][col] != 0) return solveSudoku(grid, row, col + 1); for (let num = 1; num < 10; num++) { // Check if it is safe to place // the num (1-9) in the given // row ,col ->we move to next column if (isSafe(grid, row, col, num)) { /* assigning the num in the current (row,col) position of the grid and assuming our assigned num in the position is correct */ grid[row][col] = num; // Checking for next // possibility with next column if (solveSudoku(grid, row, col + 1)) return true ; } /* removing the assigned num , since our assumption was wrong , and we go for next assumption with diff num value */ grid[row][col] = 0; } return false ; } /* A utility function to print grid */ function print(grid) { for (let i = 0; i < N; i++) { for (let j = 0; j < N; j++) document.write(grid[i][j] + " " ); document.write( "<br>" ); } } // Check whether it will be legal // to assign num to the // given row, col function isSafe(grid, row, col, num) { // Check if we find the same num // in the similar row , we // return false for (let x = 0; x <= 8; x++) if (grid[row][x] == num) return false ; // Check if we find the same num // in the similar column , // we return false for (let x = 0; x <= 8; x++) if (grid[x][col] == num) return false ; // Check if we find the same num // in the particular 3*3 // matrix, we return false let startRow = row - row % 3, startCol = col - col % 3; for (let i = 0; i < 3; i++) for (let j = 0; j < 3; j++) if (grid[i + startRow][j + startCol] == num) return false ; return true ; } // Driver Code let 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, 0, 0)) print(grid) else document.write( "no solution exists " ) // This code is contributed by rag2127 </script> |
3 1 6 5 7 8 4 9 2 5 2 9 1 3 4 7 6 8 4 8 7 6 2 9 5 3 1 2 6 3 4 1 5 9 8 7 9 7 4 8 6 3 1 2 5 8 5 1 7 9 2 6 4 3 1 3 8 9 4 7 2 5 6 6 9 2 3 5 1 8 7 4 7 4 5 2 8 6 3 1 9
Time complexity: O(9(N*N)), For every unassigned index, there are 9 possible options so the time complexity is O(9^(n*n)).
Space Complexity: O(N*N), To store the output array a matrix is needed.
Sudoku using Backtracking:
Like all other Backtracking problems, Sudoku can be solved by assigning numbers one by one to empty cells. Before assigning a number, check whether it is safe to assign.
Check that the same number is not present in the current row, current column and current 3X3 subgrid. After checking for safety, assign the number, and recursively check whether this assignment leads to a solution or not. If the assignment doesn’t lead to a solution, then try the next number for the current empty cell. And if none of the number (1 to 9) leads to a solution, return false and print no solution exists.
Follow the steps below to solve the problem:
- Create a function that checks after assigning the current index the grid becomes unsafe or not. Keep Hashmap for a row, column and boxes. If any number has a frequency greater than 1 in the hashMap return false else return true; hashMap can be avoided by using loops.
- Create a recursive function that takes a grid.
- Check for any unassigned location.
- If present then assigns a number from 1 to 9.
- Check if assigning the number to current index makes the grid unsafe or not.
- If safe then recursively call the function for all safe cases from 0 to 9.
- If any recursive call returns true, end the loop and return true. If no recursive call returns true then return false.
- If there is no unassigned location then return true.
Below is the implementation of the above approach:
C++
// A Backtracking program in // C++ to solve Sudoku problem #include <bits/stdc++.h> using namespace std; // UNASSIGNED is used for empty // cells in sudoku grid #define UNASSIGNED 0 // N is used for the size of Sudoku grid. // Size will be NxN #define N 9 // This function finds an entry in grid // that is still unassigned bool FindUnassignedLocation( int grid[N][N], int & row, int & col); // Checks whether it will be legal // to assign num to the given row, col bool isSafe( int grid[N][N], int row, int col, int num); /* 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 SolveSudoku( int grid[N][N]) { int row, col; // If there is no unassigned location, // we are done if (!FindUnassignedLocation(grid, row, col)) // success! return true ; // Consider digits 1 to 9 for ( int num = 1; num <= 9; num++) { // Check if looks promising if (isSafe(grid, row, col, num)) { // Make tentative assignment grid[row][col] = num; // Return, if success if (SolveSudoku(grid)) return true ; // Failure, unmake & try again grid[row][col] = UNASSIGNED; } } // This triggers backtracking return false ; } /* Searches the grid to find an entry that is still unassigned. If found, the reference parameters row, col will be set the location that is unassigned, and true is returned. If no unassigned entries remain, false is returned. */ bool FindUnassignedLocation( int grid[N][N], int & row, int & col) { for (row = 0; row < N; row++) for (col = 0; col < N; col++) if (grid[row][col] == UNASSIGNED) return true ; return false ; } /* Returns a boolean which indicates whether an assigned entry in the specified row matches the given number. */ bool UsedInRow( int grid[N][N], int row, int num) { for ( int col = 0; col < N; col++) if (grid[row][col] == num) return true ; return false ; } /* Returns a boolean which indicates whether an assigned entry in the specified column matches the given number. */ bool UsedInCol( int grid[N][N], int col, int num) { for ( int row = 0; row < N; row++) if (grid[row][col] == num) return true ; return false ; } /* Returns a boolean which indicates whether an assigned entry within the specified 3x3 box matches the given number. */ bool UsedInBox( int grid[N][N], int boxStartRow, int boxStartCol, int num) { for ( int row = 0; row < 3; row++) for ( int col = 0; col < 3; col++) if (grid[row + boxStartRow] [col + boxStartCol] == num) return true ; return false ; } /* Returns a boolean which indicates whether it will be legal to assign num to the given row, col location. */ bool isSafe( int grid[N][N], int row, int col, int num) { /* Check if 'num' is not already placed in current row, current column and current 3x3 box */ return !UsedInRow(grid, row, num) && !UsedInCol(grid, col, num) && !UsedInBox(grid, row - row % 3, col - col % 3, num) && grid[row][col] == UNASSIGNED; } /* 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; } } // 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; } // This is code is contributed by rathbhupendra |
Java
/* A Backtracking program in Java to solve Sudoku problem */ class GFG { public static boolean isSafe( int [][] board, int row, int col, int num) { // Row has the unique (row-clash) for ( int d = 0 ; d < board.length; d++) { // Check if the number we are trying to // place is already present in // that row, return false; if (board[row][d] == num) { return false ; } } // Column has the unique numbers (column-clash) for ( int r = 0 ; r < board.length; r++) { // Check if the number // we are trying to // place is already present in // that column, return false; if (board[r][col] == num) { return false ; } } // Corresponding square has // unique number (box-clash) int sqrt = ( int )Math.sqrt(board.length); int boxRowStart = row - row % sqrt; int boxColStart = col - col % sqrt; for ( int r = boxRowStart; r < boxRowStart + sqrt; r++) { for ( int d = boxColStart; d < boxColStart + sqrt; d++) { if (board[r][d] == num) { return false ; } } } // if there is no clash, it's safe return true ; } public static boolean solveSudoku( int [][] board, int n) { int row = - 1 ; int col = - 1 ; boolean isEmpty = true ; for ( int i = 0 ; i < n; i++) { for ( int j = 0 ; j < n; j++) { if (board[i][j] == 0 ) { row = i; col = j; // We still have some remaining // missing values in Sudoku isEmpty = false ; break ; } } if (!isEmpty) { break ; } } // No empty space left if (isEmpty) { return true ; } // Else for each-row backtrack for ( int num = 1 ; num <= n; num++) { if (isSafe(board, row, col, num)) { board[row][col] = num; if (solveSudoku(board, n)) { // print(board, n); return true ; } else { // replace it board[row][col] = 0 ; } } } return false ; } public static void print( int [][] board, int N) { // We got the answer, just print it for ( int r = 0 ; r < N; r++) { for ( int d = 0 ; d < N; d++) { System.out.print(board[r][d]); System.out.print( " " ); } System.out.print( "\n" ); if ((r + 1 ) % ( int )Math.sqrt(N) == 0 ) { System.out.print( "" ); } } } // Driver Code public static void main(String args[]) { int [][] board = new int [][] { { 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 } }; int N = board.length; if (solveSudoku(board, N)) { // print solution print(board, N); } else { System.out.println( "No solution" ); } } } // This code is contributed // by MohanDas |
Python3
# A Backtracking program # in Python to solve Sudoku problem # A Utility Function to print the Grid def print_grid(arr): for i in range ( 9 ): for j in range ( 9 ): print (arr[i][j], end = " " ), print () # Function to Find the entry in # the Grid that is still not used # Searches the grid to find an # entry that is still unassigned. If # found, the reference parameters # row, col will be set the location # that is unassigned, and true is # returned. If no unassigned entries # remains, false is returned. # 'l' is a list variable that has # been passed from the solve_sudoku function # to keep track of incrementation # of Rows and Columns def find_empty_location(arr, l): for row in range ( 9 ): for col in range ( 9 ): if (arr[row][col] = = 0 ): l[ 0 ] = row l[ 1 ] = col return True return False # Returns a boolean which indicates # whether any assigned entry # in the specified row matches # the given number. def used_in_row(arr, row, num): for i in range ( 9 ): if (arr[row][i] = = num): return True return False # Returns a boolean which indicates # whether any assigned entry # in the specified column matches # the given number. def used_in_col(arr, col, num): for i in range ( 9 ): if (arr[i][col] = = num): return True return False # Returns a boolean which indicates # whether any assigned entry # within the specified 3x3 box # matches the given number def used_in_box(arr, row, col, num): for i in range ( 3 ): for j in range ( 3 ): if (arr[i + row][j + col] = = num): return True return False # Checks whether it will be legal # to assign num to the given row, col # Returns a boolean which indicates # whether it will be legal to assign # num to the given row, col location. def check_location_is_safe(arr, row, col, num): # Check if 'num' is not already # placed in current row, # current column and current 3x3 box return ( not used_in_row(arr, row, num) and ( not used_in_col(arr, col, num) and ( not used_in_box(arr, row - row % 3 , col - col % 3 , num)))) # 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_sudoku(arr): # 'l' is a list variable that keeps the # record of row and col in # find_empty_location Function l = [ 0 , 0 ] # If there is no unassigned # location, we are done if ( not find_empty_location(arr, l)): return True # Assigning list values to row and col # that we got from the above Function row = l[ 0 ] col = l[ 1 ] # consider digits 1 to 9 for num in range ( 1 , 10 ): # if looks promising if (check_location_is_safe(arr, row, col, num)): # make tentative assignment arr[row][col] = num # return, if success, # ya ! if (solve_sudoku(arr)): return True # failure, unmake & try again arr[row][col] = 0 # this triggers backtracking return False # Driver main function to test above functions if __name__ = = "__main__" : # creating a 2D array for the grid grid = [[ 0 for x in range ( 9 )] for y in range ( 9 )] # assigning values to the grid 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 success print the grid if (solve_sudoku(grid)): print_grid(grid) else : print ( "No solution exists" ) # The above code has been contributed by Harshit Sidhwa. |
C#
/* A Backtracking program in C# to solve Sudoku problem */ using System; class GFG { public static bool isSafe( int [, ] board, int row, int col, int num) { // Row has the unique (row-clash) for ( int d = 0; d < board.GetLength(0); d++) { // Check if the number // we are trying to // place is already present in // that row, return false; if (board[row, d] == num) { return false ; } } // Column has the unique numbers (column-clash) for ( int r = 0; r < board.GetLength(0); r++) { // Check if the number // we are trying to // place is already present in // that column, return false; if (board[r, col] == num) { return false ; } } // corresponding square has // unique number (box-clash) int sqrt = ( int )Math.Sqrt(board.GetLength(0)); int boxRowStart = row - row % sqrt; int boxColStart = col - col % sqrt; for ( int r = boxRowStart; r < boxRowStart + sqrt; r++) { for ( int d = boxColStart; d < boxColStart + sqrt; d++) { if (board[r, d] == num) { return false ; } } } // if there is no clash, it's safe return true ; } public static bool solveSudoku( int [, ] board, int n) { int row = -1; int col = -1; bool isEmpty = true ; for ( int i = 0; i < n; i++) { for ( int j = 0; j < n; j++) { if (board[i, j] == 0) { row = i; col = j; // We still have some remaining // missing values in Sudoku isEmpty = false ; break ; } } if (!isEmpty) { break ; } } // no empty space left if (isEmpty) { return true ; } // else for each-row backtrack for ( int num = 1; num <= n; num++) { if (isSafe(board, row, col, num)) { board[row, col] = num; if (solveSudoku(board, n)) { // Print(board, n); return true ; } else { // Replace it board[row, col] = 0; } } } return false ; } public static void print( int [, ] board, int N) { // We got the answer, just print it for ( int r = 0; r < N; r++) { for ( int d = 0; d < N; d++) { Console.Write(board[r, d]); Console.Write( " " ); } Console.Write( "\n" ); if ((r + 1) % ( int )Math.Sqrt(N) == 0) { Console.Write( "" ); } } } // Driver Code public static void Main(String[] args) { int [, ] board = new int [, ] { { 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 } }; int N = board.GetLength(0); if (solveSudoku(board, N)) { // print solution print(board, N); } else { Console.Write( "No solution" ); } } } // This code has been contributed by 29AjayKumar |
Javascript
<script> /* A Backtracking program in Javascript to solve Sudoku problem */ function isSafe(board, row, col, num) { // Row has the unique (row-clash) for (let d = 0; d < board.length; d++) { // Check if the number we are trying to // place is already present in // that row, return false; if (board[row][d] == num) { return false ; } } // Column has the unique numbers (column-clash) for (let r = 0; r < board.length; r++) { // Check if the number // we are trying to // place is already present in // that column, return false; if (board[r][col] == num) { return false ; } } // Corresponding square has // unique number (box-clash) let sqrt = Math.floor(Math.sqrt(board.length)); let boxRowStart = row - row % sqrt; let boxColStart = col - col % sqrt; for (let r = boxRowStart; r < boxRowStart + sqrt; r++) { for (let d = boxColStart; d < boxColStart + sqrt; d++) { if (board[r][d] == num) { return false ; } } } // If there is no clash, it's safe return true ; } function solveSudoku(board, n) { let row = -1; let col = -1; let isEmpty = true ; for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { if (board[i][j] == 0) { row = i; col = j; // We still have some remaining // missing values in Sudoku isEmpty = false ; break ; } } if (!isEmpty) { break ; } } // No empty space left if (isEmpty) { return true ; } // Else for each-row backtrack for (let num = 1; num <= n; num++) { if (isSafe(board, row, col, num)) { board[row][col] = num; if (solveSudoku(board, n)) { // print(board, n); return true ; } else { // Replace it board[row][col] = 0; } } } return false ; } function print(board, N) { // We got the answer, just print it for (let r = 0; r < N; r++) { for (let d = 0; d < N; d++) { document.write(board[r][d]); document.write( " " ); } document.write( "<br>" ); if ((r + 1) % Math.floor(Math.sqrt(N)) == 0) { document.write( "" ); } } } // Driver Code let board = [ [ 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 ] ]; let N = board.length; if (solveSudoku(board, N)) { // Print solution print(board, N); } else { document.write( "No solution" ); } // This code is contributed by avanitrachhadiya2155 </script> |
3 1 6 5 7 8 4 9 2 5 2 9 1 3 4 7 6 8 4 8 7 6 2 9 5 3 1 2 6 3 4 1 5 9 8 7 9 7 4 8 6 3 1 2 5 8 5 1 7 9 2 6 4 3 1 3 8 9 4 7 2 5 6 6 9 2 3 5 1 8 7 4 7 4 5 2 8 6 3 1 9
Time complexity: O(9(N*N)), For every unassigned index, there are 9 possible options so the time complexity is O(9^(n*n)). The time complexity remains the same but there will be some early pruning so the time taken will be much less than the naive algorithm but the upper bound time complexity remains the same.
Space Complexity: O(N*N), To store the output array a matrix is needed.
Sudoku using Bit Masks:
This method is a slight optimization to the above 2 methods. For each row/column/box create a bitmask and for each element in the grid set the bit at position ‘value’ to 1 in the corresponding bitmasks, for O(1) checks.
Follow the steps below to solve the problem:
- Create 3 arrays of size N (one for rows, columns, and boxes).
- The boxes are indexed from 0 to 8. (in order to find the box index of an element we use the following formula: row / 3 * 3 + column / 3).
- Map the initial values of the grid first.
- Each time we add/remove an element to/from the grid set the bit to 1/0 to the corresponding bitmasks.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h> using namespace std; #define N 9 // Bitmasks for each row/column/box int row[N], col[N], box[N]; bool seted = false ; // Utility function to find the box index // of an element at position [i][j] in the grid int getBox( int i, int j) { return i / 3 * 3 + j / 3; } // Utility function to check if a number // is present in the corresponding row/column/box bool isSafe( int i, int j, int number) { return !((row[i] >> number) & 1) && !((col[j] >> number) & 1) && !((box[getBox(i, j)] >> number) & 1); } // Utility function to set the initial values of a Sudoku // board (map the values in the bitmasks) void setInitialValues( int grid[N][N]) { for ( int i = 0; i < N; i++) for ( int j = 0; j < N; j++) row[i] |= 1 << grid[i][j], col[j] |= 1 << grid[i][j], box[getBox(i, j)] |= 1 << grid[i][j]; } /* 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 SolveSudoku( int grid[N][N], int i, int j) { // Set the initial values if (!seted) seted = true , setInitialValues(grid); if (i == N - 1 && j == N) return true ; if (j == N) j = 0, i++; if (grid[i][j]) return SolveSudoku(grid, i, j + 1); for ( int nr = 1; nr <= N; nr++) { if (isSafe(i, j, nr)) { /* Assign nr in the current (i, j) position and add nr to each bitmask */ grid[i][j] = nr; row[i] |= 1 << nr; col[j] |= 1 << nr; box[getBox(i, j)] |= 1 << nr; if (SolveSudoku(grid, i, j + 1)) return true ; // Remove nr from each bitmask // and search for another possibility row[i] &= ~(1 << nr); col[j] &= ~(1 << nr); box[getBox(i, j)] &= ~(1 << nr); } grid[i][j] = 0; } return false ; } // Utility function to print the solved grid void print( int grid[N][N]) { for ( int i = 0; i < N; i++, cout << '\n' ) for ( int j = 0; j < N; j++) cout << grid[i][j] << ' ' ; } // 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, 0, 0)) print(grid); else cout << "No solution exists\n" ; return 0; } // This code is contributed // by Gatea David |
Java
/*package whatever //do not write package name here */ import java.io.*; class GFG { static int N = 9 ; // Bitmasks for each row/column/box static int row[] = new int [N], col[] = new int [N], box[] = new int [N]; static Boolean seted = false ; // Utility function to find the box index // of an element at position [i][j] in the grid static int getBox( int i, int j) { return i / 3 * 3 + j / 3 ; } // Utility function to check if a number // is present in the corresponding row/column/box static Boolean isSafe( int i, int j, int number) { return ((row[i] >> number) & 1 ) == 0 && ((col[j] >> number) & 1 ) == 0 && ((box[getBox(i, j)] >> number) & 1 ) == 0 ; } // Utility function to set the initial values of a // Sudoku board (map the values in the bitmasks) static void setInitialValues( int grid[][]) { for ( int i = 0 ; i < grid.length; i++) { for ( int j = 0 ; j < grid.length; j++) { row[i] |= 1 << grid[i][j]; col[j] |= 1 << grid[i][j]; box[getBox(i, j)] |= 1 << grid[i][j]; } } } /* 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) */ static Boolean SolveSudoku( int grid[][], int i, int j) { // Set the initial values if (!seted) { seted = true ; setInitialValues(grid); } if (i == N - 1 && j == N) return true ; if (j == N) { j = 0 ; i++; } if (grid[i][j] > 0 ) return SolveSudoku(grid, i, j + 1 ); for ( int nr = 1 ; nr <= N; nr++) { if (isSafe(i, j, nr)) { /* Assign nr in the current (i, j) position and add nr to each bitmask */ grid[i][j] = nr; row[i] |= 1 << nr; col[j] |= 1 << nr; box[getBox(i, j)] |= 1 << nr; if (SolveSudoku(grid, i, j + 1 )) return true ; // Remove nr from each bitmask // and search for another possibility row[i] &= ~( 1 << nr); col[j] &= ~( 1 << nr); box[getBox(i, j)] &= ~( 1 << nr); } grid[i][j] = 0 ; } return false ; } // Utility function to print the solved grid static void print( int grid[][]) { for ( int i = 0 ; i < grid.length; i++) { for ( int j = 0 ; j < grid[ 0 ].length; j++) { System.out.printf( "%d " , grid[i][j]); } System.out.println(); } } // 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, 0 , 0 )) print(grid); else System.out.println( "No solution exists" ); } } // This code is contributed by shinjanpatra. |
Python3
# N is the size of the 2D matrix N*N N = 9 # A utility function to print grid def printing(arr): for i in range (N): for j in range (N): print (arr[i][j], end = " " ) print () # Checks whether it will be # legal to assign num to the # given row, col def isSafe(grid, row, col, num): # Check if we find the same num # in the similar row , we # return false for x in range ( 9 ): if grid[row][x] = = num: return False # Check if we find the same num in # the similar column , we # return false for x in range ( 9 ): if grid[x][col] = = num: return False # Check if we find the same num in # the particular 3*3 matrix, # we return false startRow = row - row % 3 startCol = col - col % 3 for i in range ( 3 ): for j in range ( 3 ): if grid[i + startRow][j + startCol] = = num: return False return True # 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 solveSudoku(grid, row, col): # Check if we have reached the 8th # row and 9th column (0 # indexed matrix) , we are # returning true to avoid # further backtracking if (row = = N - 1 and col = = N): return True # Check if column value becomes 9 , # we move to next row and # column start from 0 if col = = N: row + = 1 col = 0 # Check if the current position of # the grid already contains # value >0, we iterate for next column if grid[row][col] > 0 : return solveSudoku(grid, row, col + 1 ) for num in range ( 1 , N + 1 , 1 ): # Check if it is safe to place # the num (1-9) in the # given row ,col ->we # move to next column if isSafe(grid, row, col, num): # Assigning the num in # the current (row,col) # position of the grid # and assuming our assigned # num in the position # is correct grid[row][col] = num # Checking for next possibility with next # column if solveSudoku(grid, row, col + 1 ): return True # Removing the assigned num , # since our assumption # was wrong , and we go for # next assumption with # diff num value grid[row][col] = 0 return False # Driver Code # 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, 0 , 0 )): printing(grid) else : print ( "no solution exists " ) # This code is contributed by sanjoy_62. |
C#
// C# program for above approach using System; class GFG { // N is the size of the 2D matrix N*N static int N = 9; /* 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) */ static bool solveSudoku( int [, ] grid, int row, int col) { /*if we have reached the 8th row and 9th column (0 indexed matrix) , we are returning true to avoid further backtracking */ if (row == N - 1 && col == N) return true ; // Check if column value becomes 9 , // we move to next row // and column start from 0 if (col == N) { row++; col = 0; } // Check if the current position // of the grid already // contains value >0, we iterate // for next column if (grid[row, col] != 0) return solveSudoku(grid, row, col + 1); for ( int num = 1; num < 10; num++) { // Check if it is safe to place // the num (1-9) in the // given row ,col ->we move to next column if (isSafe(grid, row, col, num)) { /* assigning the num in the current (row,col) position of the grid and assuming our assigned num in the position is correct */ grid[row, col] = num; // Checking for next // possibility with next column if (solveSudoku(grid, row, col + 1)) return true ; } /* removing the assigned num , since our assumption was wrong , and we go for next assumption with diff num value */ grid[row, col] = 0; } return false ; } /* A utility function to print grid */ static void print( int [, ] grid) { for ( int i = 0; i < N; i++) { for ( int j = 0; j < N; j++) Console.Write(grid[i, j] + " " ); Console.WriteLine(); } } // Check whether it will be legal // to assign num to the // given row, col static bool isSafe( int [, ] grid, int row, int col, int num) { // Check if we find the same num // in the similar row , we // return false for ( int x = 0; x <= 8; x++) if (grid[row, x] == num) return false ; // Check if we find the same num // in the similar column , // we return false for ( int x = 0; x <= 8; x++) if (grid[x, col] == num) return false ; // Check if we find the same num // in the particular 3*3 // matrix, we return false int startRow = row - row % 3, startCol = col - col % 3; for ( int i = 0; i < 3; i++) for ( int j = 0; j < 3; j++) if (grid[i + startRow, j + startCol] == num) return false ; return true ; } // Driver code static void Main() { 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, 0, 0)) print(grid); else Console.WriteLine( "No Solution exists" ); } } // This code is contributed by code_hunt. |
Javascript
<script> const N = 9 // Bitmasks for each row/column/box let row = new Array(N), col = new Array(N), box = new Array(N); let seted = false ; // Utility function to find the box index // of an element at position [i][j] in the grid function getBox(i,j) { return Math.floor(i / 3) * 3 + Math.floor(j / 3); } // Utility function to check if a number // is present in the corresponding row/column/box function isSafe(i,j,number) { return !((row[i] >> number) & 1) && !((col[j] >> number) & 1) && !((box[getBox(i,j)] >> number) & 1); } // Utility function to set the initial values of a Sudoku board // (map the values in the bitmasks) function setInitialValues(grid) { for (let i = 0; i < N;i++) for (let j = 0; j < N; j++) row[i] |= 1 << grid[i][j], col[j] |= 1 << grid[i][j], box[getBox(i, j)] |= 1 << grid[i][j]; } /* 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) */ function SolveSudoku(grid ,i, j) { // Set the initial values if (!seted){ seted = true , setInitialValues(grid); } if (i == N - 1 && j == N) return true ; if (j == N){ j = 0; i++; } if (grid[i][j]) return SolveSudoku(grid, i, j + 1); for (let nr = 1; nr <= N;nr++) { if (isSafe(i, j, nr)) { /* Assign nr in the current (i, j) position and add nr to each bitmask */ grid[i][j] = nr; row[i] |= 1 << nr; col[j] |= 1 << nr; box[getBox(i, j)] |= 1 << nr; if (SolveSudoku(grid, i,j + 1)) return true ; // Remove nr from each bitmask // and search for another possibility row[i] &= ~(1 << nr); col[j] &= ~(1 << nr); box[getBox(i, j)] &= ~(1 << nr); } grid[i][j] = 0; } return false ; } // Utility function to print the solved grid function print(grid) { for (let i = 0; i < N; i++){ for (let j = 0; j < N; j++){ document.write(grid[i][j], " " ); } document.write( "</br>" ); } } // Driver Code // 0 means unassigned cells let 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,0 ,0)) print(grid); else document.write( "No solution exists" , "</br>" ); // This code is contributed by shinjanpatra </script> |
3 1 6 5 7 8 4 9 2 5 2 9 1 3 4 7 6 8 4 8 7 6 2 9 5 3 1 2 6 3 4 1 5 9 8 7 9 7 4 8 6 3 1 2 5 8 5 1 7 9 2 6 4 3 1 3 8 9 4 7 2 5 6 6 9 2 3 5 1 8 7 4 7 4 5 2 8 6 3 1 9
Time complexity: O(9(N*N)). For every unassigned index, there are 9 possible options so the time complexity is O(9^(n*n)). The time complexity remains the same but checking if a number is safe to use is much faster, O(1).
Space Complexity: O(N*N). To store the output array a matrix is needed, and 3 extra arrays of size n are needed for the bitmasks.
Sudoku using Cross-Hatching with backtracking:
This method is an optimization of the above method 2. It runs 5X times faster than method 2. Like we used to fill sudoku by first identifying the element which is almost filled. It starts with identifying the row and column where the element should be placed. Picking the almost-filled elements first will give better pruning.
Follow the steps below to solve the problem:
- Build a graph with pending elements mapped to row and column coordinates where they can be fitted in the original matrix.
- Pick the elements from the graph sorted by fewer remaining elements to be filled.
- Recursively fill the elements using a graph into the matrix. Backtrack once an unsafe position is discovered.
Below is the implementation of the above approach:
C++
// C++ Code #include <algorithm> #include <bits/stdc++.h> #include <map> #include <vector> using namespace std; // Input matrix vector<vector< int > > arr = { { 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 } }; // Position of the input elements in the arr // pos = { // element: [[position 1], [position 2]] // } map< int , vector<vector< int > > > pos; // Count of the remaining number of the elements // rem = { // element: pending count // } map< int , int > rem; // Graph defining tentative positions of the elements to be // filled graph = { // key: { // row1: [columns], // row2: [columns] // } // } map< int , map< int , vector< int > > > graph; // Print the matrix array void printMatrix() { for ( int i = 0; i < 9; i++) { for ( int j = 0; j < 9; j++) { cout << arr[i][j] << " " ; } cout << endl; } } // Method to check if the inserted element is safe bool is_safe( int x, int y) { int key = arr[x][y]; for ( int i = 0; i < 9; i++) { if (i != y && arr[x][i] == key) { return false ; } if (i != x && arr[i][y] == key) { return false ; } } int r_start = floor (x / 3) * 3; int r_end = r_start + 3; int c_start = floor (y / 3) * 3; int c_end = c_start + 3; for ( int i = r_start; i < r_end; i++) { for ( int j = c_start; j < c_end; j++) { if (i != x && j != y && arr[i][j] == key) { return false ; } } } return true ; } // method to fill the matrix // input keys: list of elements to be filled in the matrix // k : index number of the element to be picked up // from keys rows: list of row index where element is // to be inserted r : index number of the row to be // inserted // bool fill_matrix( int k, vector< int > keys, int r, vector< int > rows) { int c = 0; arr[rows[r]] = keys[k]; if (is_safe(rows[r], c)) { if (r < rows.size() - 1) { if (fill_matrix(k, keys, r + 1, rows)) { return true ; } else { arr[rows[r]] = 0; } } else { if (k < keys.size() - 1) { if (fill_matrix( k + 1, keys, 0, rows)) { return true ; } else { arr[rows[r]] = 0; } } return true ; } } arr[rows[r]] = 0; return false ; } // Fill the pos and rem dictionary. It will be used to build // graph void build_pos_and_rem() { for ( int i = 0; i < 9; i++) { for ( int j = 0; j < 9; j++) { if (arr[i][j] > 0) { if (!pos.count(arr[i][j])) { pos[arr[i][j]] = {}; } pos[arr[i][j]].push_back({ i, j }); if (!rem.count(arr[i][j])) { rem[arr[i][j]] = 9; } rem[arr[i][j]] -= 1; } } } // Fill the elements not present in input matrix. // Example: 1 is missing in input matrix for ( int i = 1; i < 10; i++) { if (!pos.count(i)) { pos[i] = {}; } if (!rem.count(i)) { rem[i] = 9; } } } int main() { printMatrix(); } // This code is contributed by ishankhandelwals. |
Python3
# This program works by identifying the remaining elements and backtrack only on those. # The elements are inserted in the increasing order of the elements left to be inserted. And hence runs much faster. # Comparing with other back tracking algorithms, it runs 5X faster. # Input matrix arr = [ [ 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 ] ] # Position of the input elements in the arr # pos = { # element: [[position 1], [position 2]] # } pos = {} # Count of the remaining number of the elements # rem = { # element: pending count # } rem = {} # Graph defining tentative positions of the elements to be filled # graph = { # key: { # row1: [columns], # row2: [columns] # } # } graph = {} # Print the matrix array def printMatrix(): for i in range ( 0 , 9 ): for j in range ( 0 , 9 ): print ( str (arr[i][j]), end = " " ) print () # Method to check if the inserted element is safe def is_safe(x, y): key = arr[x][y] for i in range ( 0 , 9 ): if i ! = y and arr[x][i] = = key: return False if i ! = x and arr[i][y] = = key: return False r_start = int (x / 3 ) * 3 r_end = r_start + 3 c_start = int (y / 3 ) * 3 c_end = c_start + 3 for i in range (r_start, r_end): for j in range (c_start, c_end): if i ! = x and j ! = y and arr[i][j] = = key: return False return True # method to fill the matrix # input keys: list of elements to be filled in the matrix # k : index number of the element to be picked up from keys # rows: list of row index where element is to be inserted # r : index number of the row to be inserted # def fill_matrix(k, keys, r, rows): for c in graph[keys[k]][rows[r]]: if arr[rows[r]] > 0 : continue arr[rows[r]] = keys[k] if is_safe(rows[r], c): if r < len (rows) - 1 : if fill_matrix(k, keys, r + 1 , rows): return True else : arr[rows[r]] = 0 continue else : if k < len (keys) - 1 : if fill_matrix(k + 1 , keys, 0 , list (graph[keys[k + 1 ]].keys())): return True else : arr[rows[r]] = 0 continue return True arr[rows[r]] = 0 return False # Fill the pos and rem dictionary. It will be used to build graph def build_pos_and_rem(): for i in range ( 0 , 9 ): for j in range ( 0 , 9 ): if arr[i][j] > 0 : if arr[i][j] not in pos: pos[arr[i][j]] = [] pos[arr[i][j]].append([i, j]) if arr[i][j] not in rem: rem[arr[i][j]] = 9 rem[arr[i][j]] - = 1 # Fill the elements not present in input matrix. Example: 1 is missing in input matrix for i in range ( 1 , 10 ): if i not in pos: pos[i] = [] if i not in rem: rem[i] = 9 # Build the graph def build_graph(): for k, v in pos.items(): if k not in graph: graph[k] = {} row = list ( range ( 0 , 9 )) col = list ( range ( 0 , 9 )) for cord in v: row.remove(cord[ 0 ]) col.remove(cord[ 1 ]) if len (row) = = 0 or len (col) = = 0 : continue for r in row: for c in col: if arr[r] = = 0 : if r not in graph[k]: graph[k][r] = [] graph[k][r].append(c) build_pos_and_rem() # Sort the rem map in order to start with smaller number of elements to be filled first. Optimization for pruning rem = {k: v for k, v in sorted (rem.items(), key = lambda item: item[ 1 ])} build_graph() key_s = list (rem.keys()) # Util called to fill the matrix fill_matrix( 0 , key_s, 0 , list (graph[key_s[ 0 ]].keys())) printMatrix() # This code is contributed by Arun Kumar |
Javascript
// convert below python code to js code // # This program works by identifying the remaining elements and backtrack only on those. // # The elements are inserted in the increasing order of the elements left to be inserted. And hence runs much faster. // # Comparing with other back tracking algorithms, it runs 5X faster. // # Input matrix // arr = [ // [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] // ] // # Position of the input elements in the arr // # pos = { // # element: [[position 1], [position 2]] // # } // pos = {} // # Count of the remaining number of the elements // # rem = { // # element: pending count // # } // rem = {} // # Graph defining tentative positions of the elements to be filled // # graph = { // # key: { // # row1: [columns], // # row2: [columns] // # } // # } // graph = {} // # Print the matrix array // def printMatrix(): // for i in range(0, 9): // for j in range(0, 9): // print(str(arr[i][j]), end=" ") // print() // # Method to check if the inserted element is safe // def is_safe(x, y): // key = arr[x][y] // for i in range(0, 9): // if i != y and arr[x][i] == key: // return False // if i != x and arr[i][y] == key: // return False // r_start = int(x / 3) * 3 // r_end = r_start + 3 // c_start = int(y / 3) * 3 // c_end = c_start + 3 // for i in range(r_start, r_end): // for j in range(c_start, c_end): // if i != x and j != y and arr[i][j] == key: // return False // return True // # method to fill the matrix // # input keys: list of elements to be filled in the matrix // # k : index number of the element to be picked up from keys // # rows: list of row index where element is to be inserted // # r : index number of the row to be inserted // # // def fill_matrix(k, keys, r, rows): // for c in graph[keys[k]][rows[r]]: // if arr[rows[r]] > 0: // continue // arr[rows[r]] = keys[k] // if is_safe(rows[r], c): // if r < len(rows) - 1: // if fill_matrix(k, keys, r + 1, rows): // return True // else: // arr[rows[r]] = 0 // continue // else: // if k < len(keys) - 1: // if fill_matrix(k + 1, keys, 0, list(graph[keys[k + 1]].keys())): // return True // else: // arr[rows[r]] = 0 // continue // return True // arr[rows[r]] = 0 // return False // # Fill the pos and rem dictionary. It will be used to build graph // def build_pos_and_rem(): // for i in range(0, 9): // for j in range(0, 9): // if arr[i][j] > 0: // if arr[i][j] not in pos: // pos[arr[i][j]] = [] // pos[arr[i][j]].append([i, j]) // if arr[i][j] not in rem: // rem[arr[i][j]] = 9 // rem[arr[i][j]] -= 1 // # Fill the elements not present in input matrix. Example: 1 is missing in input matrix // for i in range(1, 10): // if i not in pos: // pos[i] = [] // if i not in rem: // rem[i] = 9 // # Build the graph // def build_graph(): // for k, v in pos.items(): // if k not in graph: // graph[k] = {} // row = list(range(0, 9)) // col = list(range(0, 9)) // for cord in v: // row.remove(cord[0]) // col.remove(cord[1]) // if len(row) == 0 or len(col) == 0: // continue // for r in row: // for c in col: // if arr[r] == 0: // if r not in graph[k]: // graph[k][r] = [] // graph[k][r].append(c) // build_pos_and_rem() // # Sort the rem map in order to start with smaller number of elements to be filled first. Optimization for pruning // rem = {k: v for k, v in sorted(rem.items(), key=lambda item: item[1])} // build_graph() // key_s = list(rem.keys()) // # Util called to fill the matrix // fill_matrix(0, key_s, 0, list(graph[key_s[0]].keys())) // printMatrix() // # This code is contributed by Arun Kumar // JavaScript Code // Input matrix let arr = [ [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] ] // Position of the input elements in the arr // pos = { // element: [[position 1], [position 2]] // } let pos = {}; // Count of the remaining number of the elements // rem = { // element: pending count // } let rem = {}; // Graph defining tentative positions of the elements to be filled // graph = { // key: { // row1: [columns], // row2: [columns] // } // } let graph = {}; // Print the matrix array function printMatrix() { for (let i = 0; i < 9; i++) { for (let j = 0; j < 9; j++) { process.stdout.write(arr[i][j]+ " " ); } console.log(); } } // Method to check if the inserted element is safe function is_safe(x, y) { let key = arr[x][y]; for (let i = 0; i < 9; i++) { if (i !== y && arr[x][i] === key) { return false ; } if (i !== x && arr[i][y] === key) { return false ; } } let r_start = Math.floor(x / 3) * 3; let r_end = r_start + 3; let c_start = Math.floor(y / 3) * 3; let c_end = c_start + 3; for (let i = r_start; i < r_end; i++) { for (let j = c_start; j < c_end; j++) { if (i !== x && j !== y && arr[i][j] === key) { return false ; } } } return true ; } // method to fill the matrix // input keys: list of elements to be filled in the matrix // k : index number of the element to be picked up from keys // rows: list of row index where element is to be inserted // r : index number of the row to be inserted // function fill_matrix(k, keys, r, rows) { for (let c of graph[keys[k]][rows[r]]) { if (arr[rows[r]] > 0) { continue ; } arr[rows[r]] = keys[k]; if (is_safe(rows[r], c)) { if (r < rows.length - 1) { if (fill_matrix(k, keys, r + 1, rows)) { return true ; } else { arr[rows[r]] = 0; continue ; } } else { if (k < keys.length - 1) { if (fill_matrix(k + 1, keys, 0, list(graph[keys[k + 1]].keys()))) { return true ; } else { arr[rows[r]] = 0; continue ; } } return true ; } } arr[rows[r]] = 0; } return false ; } // Fill the pos and rem dictionary. It will be used to build graph function build_pos_and_rem() { for (let i = 0; i < 9; i++) { for (let j = 0; j < 9; j++) { if (arr[i][j] > 0) { if (!pos.hasOwnProperty(arr[i][j])) { pos[arr[i][j]] = []; } pos[arr[i][j]].push([i, j]); if (!rem.hasOwnProperty(arr[i][j])) { rem[arr[i][j]] = 9; } rem[arr[i][j]] -= 1; } } } // Fill the elements not present in input matrix. Example: 1 is missing in input matrix for (let i = 1; i < 10; i++) { if (!pos.hasOwnProperty(i)) { pos[i] = []; } if (!rem.hasOwnProperty(i)) { rem[i] = 9; } } } // Build the graph function build_graph() { for (let [k, v] of Object.entries(pos)) { if (!graph.hasOwnProperty(k)) { graph[k] = {}; } let row = [...Array(9).keys()]; let col = [...Array(9).keys()]; for (let cord of v) { row.splice(row.indexOf(cord[0]), 1); col.splice(col.indexOf(cord[1]), 1); } if (row.length === 0 || col.length === 0) { continue ; } for (let r of row) { for (let c of col) { if (arr[r] === 0) { if (!graph[k].hasOwnProperty(r)) { graph[k][r] = []; } graph[k][r].push(c); } } } } } build_pos_and_rem(); // Sort the rem map in order to start with smaller number of elements to be filled first. Optimization for pruning rem = Object.fromEntries(Object.entries(rem).sort((a, b) => a[1] - b[1])); build_graph(); let key_s = Object.keys(rem); // Util called to fill the matrix fill_matrix(0, key_s, 0, Object.keys(graph[key_s[0]])); printMatrix(); |
Java
// Java code import java.util.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; class Element { int row, col; List<Integer> candidates; Element( int row, int col) { this .row = row; this .col = col; this .candidates = new ArrayList<>(); } } // Input matrix class Main { static final int N = 9 ; static 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 } }; static List<Element> graph; // Method to check if the inserted element is safe static boolean isSafe( int row, int col, int num) { // check row for ( int i = 0 ; i < N; i++) { if (grid[row][i] == num) { return false ; } } // check column for ( int i = 0 ; i < N; i++) { if (grid[i][col] == num) { return false ; } } // check subgrid int subgridRow = row - row % 3 ; int subgridCol = col - col % 3 ; for ( int i = subgridRow; i < subgridRow + 3 ; i++) { for ( int j = subgridCol; j < subgridCol + 3 ; j++) { if (grid[i][j] == num) { return false ; } } } return true ; } //initialize the graph static void initializeGraph() { graph = new ArrayList<>(); for ( int row = 0 ; row < N; ++row) { for ( int col = 0 ; col < N; ++col) { if (grid[row][col] == 0 ) { Element e = new Element(row, col); for ( int num = 1 ; num <= N; ++num) { if (isSafe(row, col, num)) { e.candidates.add(num); } } graph.add(e); } } } } // Sort the rem map in order to start with smaller number of elements //to be filled first. static int sortByFewestCandidates(Element a, Element b) { return a.candidates.size() - b.candidates.size(); } static boolean solveSudoku() { if (graph.isEmpty()) { return true ; } Collections.sort(graph, Main::sortByFewestCandidates); Element e = graph.get(graph.size() - 1 ); graph.remove(graph.size() - 1 ); // graph.pop_back(); int row = e.row; int col = e.col; for ( int i = 0 ; i < e.candidates.size(); ++i) { int num = e.candidates.get(i); if (isSafe(e.row, e.col, num)) { grid[e.row][e.col] = num; graph.remove(e); if (solveSudoku()) { return true ; } graph.add(e); Collections.sort(graph, Main::sortByFewestCandidates); grid[e.row][e.col] = 0 ; } } return false ; } public static void main(String[] args) { initializeGraph(); solveSudoku(); // print solved sudoku for ( int [] row : grid) { for ( int num : row) { System.out.print(num + " " ); } System.out.println(); } } } |
C#
// C# Code using System; using System.Collections.Generic; namespace sudoku { class Program { // Input matrix static int [,] arr = new int [9, 9] { { 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 } }; // Position of the input elements in the arr // pos = { // element: [[position 1], [position 2]] // } static Dictionary< int , List< int []>> pos = new Dictionary< int , List< int []>>(); // Count of the remaining number of the elements // rem = { // element: pending count // } static Dictionary< int , int > rem = new Dictionary< int , int >(); // Graph defining tentative positions of the elements to be // filled graph = { // key: { // row1: [columns], // row2: [columns] // } // } static Dictionary< int , Dictionary< int , List< int >>> graph = new Dictionary< int , Dictionary< int , List< int >>>(); // Print the matrix array static void PrintMatrix() { for ( int i = 0; i < 9; i++) { for ( int j = 0; j < 9; j++) { Console.Write(arr[i, j] + " " ); } Console.WriteLine(); } } // Method to check if the inserted element is safe static bool IsSafe( int x, int y) { int key = arr[x, y]; for ( int i = 0; i < 9; i++) { if (i != y && arr[x, i] == key) { return false ; } if (i != x && arr[i, y] == key) { return false ; } } int r_start = ( int )Math.Floor(( double )x / 3) * 3; int r_end = r_start + 3; int c_start = ( int )Math.Floor(( double )y / 3) * 3; int c_end = c_start + 3; for ( int i = r_start; i < r_end; i++) { for ( int j = c_start; j < c_end; j++) { if (i != x && j != y && arr[i, j] == key) { return false ; } } } return true ; } // method to fill the matrix // input keys: list of elements to be filled in the matrix // k : index number of the element to be picked up // from keys rows: list of row index where element is // to be inserted r : index number of the row to be // inserted // static bool FillMatrix( int k, List< int > keys, int r, List< int > rows) { int c = 0; arr[rows[r], c] = keys[k]; if (IsSafe(rows[r], c)) { if (r < rows.Count - 1) { if (FillMatrix(k, keys, r + 1, rows)) { return true ; } else { arr[rows[r], c] = 0; } } else { if (k < keys.Count - 1) { if (FillMatrix( k + 1, keys, 0, rows)) { return true ; } else { arr[rows[r], c] = 0; } } return true ; } } arr[rows[r], c] = 0; return false ; } // Fill the pos and rem dictionary. It will be used to build // graph static void BuildPosAndRem() { for ( int i = 0; i < 9; i++) { for ( int j = 0; j < 9; j++) { if (arr[i, j] > 0) { if (!pos.ContainsKey(arr[i, j])) { pos[arr[i, j]] = new List< int []>(); } pos[arr[i, j]].Add( new int [] { i, j }); if (!rem.ContainsKey(arr[i, j])) { rem[arr[i, j]] = 9; } rem[arr[i, j]] -= 1; } } } // Fill the elements not present in input matrix. // Example: 1 is missing in input matrix for ( int i = 1; i < 10; i++) { if (!pos.ContainsKey(i)) { pos[i] = new List< int []>(); } if (!rem.ContainsKey(i)) { rem[i] = 9; } } } static void Main( string [] args) { PrintMatrix(); } } } |
3 1 6 5 7 8 4 9 2 5 2 9 1 3 4 7 6 8 4 8 7 6 2 9 5 3 1 2 6 3 4 1 5 9 8 7 9 7 4 8 6 3 1 2 5 8 5 1 7 9 2 6 4 3 1 3 8 9 4 7 2 5 6 6 9 2 3 5 1 8 7 4 7 4 5 2 8 6 3 1 9
Time complexity: O(9^(n*n)). Due to the element that needs to fit in a cell will come earlier as we are filling almost filled elements first, it will help in less number of recursive calls. So the time taken will be much less than the naive approaches but the upper bound time complexity remains the same.
Auxiliary Space: O(n*n). A graph of the remaining positions to be filled for the respected elements is created.
Contact Us