Backtracking | Set 7 (Sudoku)

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.

Naive Algorithm
The Naive Algorithm 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.

Backtracking Algorithm
Like all other Backtracking problems, we can solve Sudoku by one by one assigning numbers to empty cells. Before assigning a number, we check whether it is safe to assign. We basically check that the same number is not present in current row, current column and current 3X3 subgrid. After checking for safety, we 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 we try next number for current empty cell. And if none of number (1 to 9) lead to solution, we return false.

```  Find row, col of an unassigned cell
If there is none, return true
For digits from 1 to 9
a) If there is no conflict for digit at row,col
assign digit to row,col and recursively try fill in rest of grid
b) If recursion successful, return true
c) Else, remove digit and try another
If all digits have been tried and nothing worked, return false
```

Following are C++ and Python implementation for Sudoku problem. It prints the completely filled grid as output.

C/C++

```// A Backtracking program  in C++ to solve Sudoku problem
#include <stdio.h>

// UNASSIGNED is used for empty cells in sudoku grid
#define UNASSIGNED 0

// N is used for 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))
return true; // success!

// consider digits 1 to 9
for (int num = 1; num <= 9; num++)
{
// if looks promising
if (isSafe(grid, row, col, num))
{
// make tentative assignment
grid[row][col] = num;

// return, if success, yay!
if (SolveSudoku(grid))
return true;

// failure, unmake & try again
grid[row][col] = UNASSIGNED;
}
}
return false; // this triggers backtracking
}

/* 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 any 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 any 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 any 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);
}

/* 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++)
printf("%2d", grid[row][col]);
printf("\n");
}
}

/* Driver Program to test above functions */
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
printf("No solution exists");

return 0;
}
```

Python

```# A Backtracking program  in Pyhton 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],
print ('\n')

# 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
# remain, false is returned.
# 'l' is a list  variablethat 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 sucess, 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 sucess print the grid
if(solve_sudoku(grid)):
print_grid(grid)
else:
print "No solution exists"
```

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
```

Company Wise Coding Practice    Topic Wise Coding Practice

• anil

During backtracking aren’t we modifying the original input too ??

• anil

ok got it, we are actually not overwriting the original input positions at all ..

• AlienOnEarth

Check FindUnassignedLocation Method. It finds unassigned location and then fills data to it. If it returns false, that means everything went well. So returning true. I hope this clears your doubt.

• Argha

//A simple c++ version

#include

#include

#include

#define UNASSIGNED 0

#define MAX 9

using namespace std;

class Sudoku

{

private:

int A[MAX][MAX];

public:

static int count;

void getPuzzle();

void display();

bool checkSquare(int i,int j,int x);//place for x within a Square

bool checkRow(int i,int j,int x);//place for x within a Row

bool checkCol(int i,int j,int x);//place for x in a Column

bool isSafe(int i,int j,int x);//all restrictions

bool FindUnassignedLocation(int &row, int &col);

bool SolveSudoku();

};

int Sudoku::count=0;

bool Sudoku::SolveSudoku()

{

count++;

ofstream out;

out.open(“Moments.txt”, std::ios_base::app);

for(int i=0;i<MAX;i++)

{

for(int j=0;j<MAX;j++)

{

out<<A[i][j]<<" ";

}

out<<endl;

}

out<<endl<<endl;

out.close();

int row, col;

if (FindUnassignedLocation(row, col)==false)

return true;

for (int num = 1; num <= 9; num++)

{

if (isSafe( row, col, num)==true)

{

A[row][col] = num;

if (SolveSudoku()==true)

return true;

A[row][col] = UNASSIGNED;

}

}

return false;

}

bool Sudoku::FindUnassignedLocation(int &row, int &col)

{

for (row = 0; row < MAX; row++)

for (col = 0; col < MAX; col++)

if (A[row][col] == UNASSIGNED)

return true;

return false;

}

bool Sudoku::isSafe(int i,int j,int x)

{

if(checkSquare(i,j,x)==false && checkRow(i,j,x)==false && checkCol(i,j,x)==false)

{

return true;

}

return false;

}

bool Sudoku::checkSquare(int i,int j,int x)

{

int m,n;

m=(i/3)*3;//Trucation for proper block idejntification

n=(j/3)*3;//Trucation for proper block idejntification

for(int p=m;p<m+3;p++)

{

for(int q=n;q<n+3;q++)

{

if (A[p][q]==x)

{

return true;

}

}

}

return false;

}

bool Sudoku::checkRow(int i,int j,int x)

{

for(int p=0;p<9;p++)

{

if(A[i][p]==x)

{

return true;

}

}

return false;

}

bool Sudoku::checkCol(int i,int j,int x)

{

for(int p=0;p<9;p++)

{

if(A[p][j]==x)

{

return true;

}

}

return false;

}

void Sudoku::display()

{

for(int i=0;i<MAX;i++)

{

for(int j=0;j<MAX;j++)

{

cout<<A[i][j]<<" ";

}

cout<<endl;

}

}

void Sudoku::getPuzzle()

{

ifstream in;

in.open("Solve.txt");

for(int i=0;i<MAX;i++)

for(int j=0;j>A[i][j];

}

int main()

{

Sudoku X;

X.getPuzzle();

X.SolveSudoku();

X.display();

cout<<endl<<endl<<"Backtracking count= "<<Sudoku::count;

getch();

return 0;

}

• KK

An improvement to FindUnassignedLocation as proposed by Skiena in The Algorithm Design Manual. This might not make any different in easy puzzles as mentioned in this page. But for the puzzle at the end of this comment, it took 20 seconds on my PC without this optimization and 1 second with it.

int SuitableVals(int grid[N][N], int row, int col)
{
int total = 0;
for (int i = 1; i < 10; i++)
{
if (isSafe(grid, row, col, i))
total++;
}
}

bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
{
int min = 10;
int cur = 0;
int retrow, retcol;
bool solfound = false;
for (retrow = 0; retrow < N; retrow++)
{
for (retcol = 0; retcol < N; retcol++)
{
if (grid[retrow][retcol] == UNASSIGNED)
{
solfound = true;
cur = SuitableVals(grid, retrow, retcol);
if (cur < min)
{
min = cur;
row = retrow;
col = retcol;
}
}
}
}
return solfound;
}

Very Hard Puzzle

{ { 0, 0, 0, 0, 0, 0, 0, 1, 2 },
{ 0, 0, 0, 0, 3, 5, 0, 0, 0 },
{ 0, 0, 0, 6, 0, 0, 0, 7, 0 },
{ 7, 0, 0, 0, 0, 0, 3, 0, 0 },
{ 0, 0, 0, 4, 0, 0, 8, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 2, 0, 0, 0, 0 },
{ 0, 8, 0, 0, 0, 0, 0, 4, 0 },
{ 0, 5, 0, 0, 0, 0, 6, 0, 0 } };

• Sanjay Agarwal

Good optimization.

• Shailedra

@admin this algo. does not give solution to many sudoku puzzle…like

{{0, 0, 6, 0, 0, 0, 0, 0, 4},
{0, 0, 0, 8, 6, 0, 7, 3, 0},
{0, 4, 0, 3, 5, 4, 0, 0, 2},
{1, 7, 0, 4, 0, 0, 6, 0, 0},
{0, 9, 0, 0, 0, 0, 0, 8, 0},
{0, 0, 8, 0, 0, 6, 0, 1, 7},
{2, 0, 0, 0, 8, 1, 0, 4, 0},
{0, 6, 7, 0, 4, 3, 0, 0, 0},
{8, 0, 0, 0, 0, 0, 3, 0, 0}} and many more test cases …
i tried many test cases…
i think it should include to find the min. number to get the optimal solution….

• charamander

I took the array b[][] to keep track of the data initially filled in the question. In this problem I gave it manually to suit the input(written at last)….b[][] contains 100 at the place already given in the quesiton and so cant be modified while solving the sudoku. I am not getting any output. I am thankful to anyone who can pull me out of this…..

whats wrong with my fill_sudoku function????

# include

# include

#define N 9

int b[N][N]={{100, 0, 100, 100, 0, 100, 100, 0, 0},

{100, 100, 0, 0, 0, 0, 0, 0, 0},

{0, 100, 100, 0, 0, 0, 0, 100, 100},

{0, 0, 100, 0, 100, 0, 0, 100, 0},

{100, 0, 0, 100, 100, 100, 0, 0, 100},

{0, 100, 0, 0, 100, 0, 100, 0, 0},

{100, 100, 0, 0, 0, 0, 100, 100, 0},

{0, 0, 0, 0, 0, 0, 0, 100, 100},

{0, 0, 100, 100, 0, 100, 100, 0, 0}};;

/* Returns a boolean which indicates whether any 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 any 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 any assigned entry

within the specified 3×3 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)

{

if(b[row][col]!=100)

{

/* Check if 'num' is not already placed in current row,

current column and current 3×3 box */

return !UsedInRow(grid, row, num) &&

!UsedInCol(grid, col, num) &&

!UsedInBox(grid, row – row%3 , col – col%3, num);

}

else

return false;

}

void printGrid(int grid[N][N])

{

for (int row = 0; row < N; row++)

{

for (int col = 0; col < N; col++)

printf("%2d", grid[row][col]);

printf("n");

}

}

void fill_sudoku(int grid[N][N],int row, int column)

{

int i=1;

if(row==8&&column==8)

printGrid(grid);

if(grid[row][column]==100)

{

if(column==8)

fill_sudoku(grid,row+1,0);

else

fill_sudoku(grid,row,column+1);

}

for(;i<=9;i++)

{

grid[row][column]=i;

if(isSafe(grid, row, column, i)==1)

{

grid[row][column]=i;

if(column==8)

{fill_sudoku(grid,row+1,column);}

else

{fill_sudoku(grid,row,column+1);}

}

}

}

int main()

{

int grid[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}};

fill_sudoku(grid,0,0);

return 0;

}

• chandeepsignh

I copied the above code in Java but it produces the same result as the default input not the output shown above.
Where am I making mistake? Please suggest.

• LinuxWorld

/* this solving the sudo ku using hashing // bashed on the // advice list and the backtracking */

#include
#include
#include
int sudoku[10][10] = { {0,0,0,0,0,0,0,0,0,0},
{0,0,8,0,0,0,9,0,7,2},
{0,6,0,0,0,0,0,0,0,4},
{0,0,5,0,0,6,0,9,0,1},
{0,2,0,0,0,0,5,0,0,0},
{0,3,7,6,1,8,4,2,9,5},
{0,0,0,0,3,0,0,0,0,6},
{0,9,0,1,0,2,0,0,4,0},
{0,5,0,0,0,0,0,0,0,9},
{0,8,4,0,9,0,0,0,2,0}}; // very hard

int row[10][10] = {0} ; // this matrix used for the hashing the row and the digit
int col[10][10] = {0} ; // this is for the hashing the column
int TCT[4][4][10] ={0} ; // three cross three (for the three cross three matrix) to hashing the 3*3 board
int counter[10] = {0};
int l = 0 ;
struct advice // this take the information of about the list of the data that can be insereted into the matrix of // the sudo ku
{
int i , j ;
int count ;
};
long int total ;

/* this method for the setting the those position that is filled already in the matrix (row , col , TCT->three cross )
// in the TCT we are using the hasing */

void initial()
{
int i , j , m,n;
for(i = 1 ; i < 10 ;i++ )
{
for(j = 1 ; j < 10 ; j++)
{
if(sudoku[i][j])
{
row[i][sudoku[i][j]] = 1 ;
col[j][sudoku[i][j]] = 1 ;
TCT[(int)ceil((double)i/3)][(int)ceil((double)j/3)][sudoku[i][j]] = 1 ;
}
}
}
}

// based on the initialization we can create the list of the of unfilled with and the possible input that is advice list
{
int i , j , k , counter[10] = {0} , m ;
l = 0 ;
for(i = 1 ; i < 10 ;i++ )
{
for(j = 1 ; j < 10 ; j++)
{
if(!sudoku[i][j])
{
for(k = 1 ; k < 10 ; k++)
counter[k] = row[i][k] || col[j][k] || TCT[(int)ceil((double)i/3)][(int)ceil((double) j/3)][k] ;

m = 1 ;
for(k = 1 ; k < 10 ; k++)
{
if(!counter[k])
counter[k] = 0 ;
}
l++ ;
}
}
}

}
void print()
{
int i,j;
for( i = 1 ; i < 10 ;i++)
{
for(j = 1; j < 10 ; j++)
printf("%d \t",sudoku[i][j]) ;
putchar('\n');
putchar('\n');
}
}

/* this is the main logic for the solving the sudo ku using hasing and the back-tracking */

int sudoku_solver(int i , int j , int lb,int ub)
{
int k,p,m,num ; // next num

if(lb == ub)
return 1 ;

for(k = 1 ; k < adv1[lb].count ; k++)
{ total++ ;
p = row[i][num] || col[j][num] || TCT[(int)ceil((double)i/3)][(int)ceil((double) j/3)][num] ; /// checking the row col and TCT
if(p == 0) // recursive call
{
sudoku[i][j] = num ;
row[i][num] = 1 ;
col[j][num] = 1 ;
TCT[(int)ceil((double)i/3)][(int)ceil((double) j/3)][num] = 1;
{
row[i][num] = 0 ;
col[j][num] = 0 ;
TCT[(int)ceil((double)i/3)][(int)ceil((double) j/3)][num] = 0 ;
sudoku[i][j] = 0;
}
else
return 1 ;
}

}
return 0 ;

}

int main()
{

initial();
print();
return 0;
}

• Gengis Khan

Never mind. I got it.

• Gengis Khan

There’s a bug. How are the row and col variables getting initialized? They aren’t even declared.

• Harshit Gupta

They are initialised by FindUnassignedLocation() …

• ``` ```
/*
Title			# SUDOKU solver in C language
Author			# Hitesh Dholaria
Email			# hitesh.dholaria@gmail.com

Input 			# Following is a sample SUDOKU problem stored in the file named "problem.txt"
# Here, 0 represents empty place
# So, our overall goal is to replace such 0-places by some appropriate numbers
# There are total of 9 rows, 9 columns and 9 blocks of size (3x3)

008000050
370009010
000140007
050020600
001908300
003060020
700084000
080200063
090000400

Time Complexity # O(rows^2) OR O(columns^2)
*/

#include<stdio.h>
#include<conio.h>

// Global array to hold main SUDOKU problem
int A[9][9];

void printProblem(void);
int isProblemSolved(void);
void eliminatePossibility(int,int);
void getStartingIndicesOfBlock(int,int,int *,int *);

// Main function
int main() {

int counter=0,number=0;
int i=0,j=0,k=0,l=0,x=0,y=0;

// First read the SUDOKU input problem into A[9][9]
printf("----- Problem -----\n\n");
printProblem();

// Main loop of the program
// Keep running this loop, until the number of valid elements in array becomes 81
// That is, until problem is solved

while(!isProblemSolved()) {

// Run this loop once for each of the numbers from 1 to 9
// Every time increment this "number" and if it is overflown, reinitialize it to 1
// This "number" is like "key" or "seed" for this main loop

number++;
if(number>9) {
number=1;
}

// Eliminate possibility of being number at some of the 0-places by assigning -1 to those places

for(i=0;i<9;i++) {
for(j=0;j<9;j++) {
if(A[i][j]==number) {
eliminatePossibility(i,j);
}
}
}

// After eliminating possibilities,
// if you find any 0-place,
// then it means, there is a possibility of this "number" being at that place.
// Count such 0-places in rows,columns and blocks
// If it is only 1, then such 0-place must be updated by this "number",
// (because of no other possibility at that 0-place and wer'e 100% sure about that!)

// Moreover, eliminate possibilities again after updation

// For all the rows

for(i=0;i<9;i++) {
counter=0;
for(j=0;j<9;j++) {
if(A[i][j]==0) {
// Save column index of this 0-place
k=j;
counter++;
}
}

if(counter==1) {
A[i][k]=number;
eliminatePossibility(i,k);
}
}

// For all the columns

for(i=0;i<9;i++) {
counter=0;
for(j=0;j<9;j++) {
if(A[j][i]==0) {
// Save row index of this 0-place
k=j;
counter++;
}
}
if(counter==1) {
A[k][i]=number;
eliminatePossibility(k,i);
}
}

// For all the blocks

for(i=0;i<9;i+=3) {
for(j=0;j<9;j+=3) {
counter=0;
for(k=i;k<i+3;k++) {
for(l=j;l<j+3;l++) {
if(A[k][l]==0) {
// Save row and column indices of this 0-place
x=k,y=l;
counter++;
}
}
}
if(counter==1) {
A[x][y]=number;
eliminatePossibility(x,y);
}
}
}
}
// Main loop ends here
// Now, problem has been solved
// So, printing the final solution

printf("\n---- Solution ----\n\n");
printProblem();
getch();
return 0;
}

// This function initializes problem array A[9][9] by reading SUDOKU elements from file

int i,j;
FILE *fp;
fp = fopen("problem.txt","r");
for(i=0;i<9;i++) {
for(j=0;j<9;j++) {
A[i][j]=fgetc(fp)-48;
}
// Skip reading '\n' into array A[9][9]
fgetc(fp);
}
fclose(fp);
}

// This function prints problem array A[9][9]

void printProblem(void) {
int i,j;
for(i=0;i<9;i++) {
for(j=0;j<9;j++) {
printf("%d ",A[i][j]);
}
printf("\n");
}
}

// This function returns 1(true), if number of valid elements(i.e. non-empty places) in A[9][9] is 81.
// Otherwise, returns 0(false)
// Also, note that whenever number of valid elements becomes 81,
// that means our SUDOKU problem has been solved completely.

int isProblemSolved(void) {
int i,j,numberOfValidElements=0;
for(i=0;i<9;i++) {
for(j=0;j<9;j++) {
if(A[i][j]>0) {
numberOfValidElements++;
} else {
A[i][j]=0;
}
}
}
if(numberOfValidElements<81) {
return 0;
} else {
return 1;
}
}

// Eliminate possibility of specific "number" being at some of the 0-places by assigning -1 to those places
// Arguments (row,column) represents indices of any arbitrary place in A[9][9]

void eliminatePossibility(int row,int column) {
int i,j;

// Eliminating possibility from all the rows corresponding to "column"
for(i=0;i<9;i++) {
if(A[i][column]==0) {
A[i][column]=-1;
}
}

// Eliminating possibility from all the columns corresponding to "row"
for(i=0;i<9;i++) {
if(A[row][i]==0) {
A[row][i]=-1;
}
}

// Eliminating possibility from all the places corresponding to "row" and "column"
getStartingIndicesOfBlock(row,column,&row,&column);

// Now, "row" and "column" contains the indices of the first element of the current block
for(i=row;i<row+3;i++) {
for(j=column;j<column+3;j++) {
if(A[i][j]==0) {
A[i][j]=-1;
}
}
}
}

// This function returns the indices of the first element of the 3x3 block
// Here, specific block is being identified by the provided indices (i,j) of A[9][9]
// Resultant indices are returned by the pointers (*rowIndex,*columnIndex) to the calling function

void getStartingIndicesOfBlock(int i,int j,int *rowIndex,int *columnIndex) {
if(i<3) {
*rowIndex=0;
} else if(i<6) {
*rowIndex=3;
} else {
*rowIndex=6;
}
if(j<3) {
*columnIndex=0;
} else if(j<6) {
*columnIndex=3;
} else {
*columnIndex=6;
}
}
``` ```
• minhaz

Don’t get it, how the row and column being updated in SolveSudko function?

• minhaz

Oops got it.

• rohit

Can you please tell me how are Rows and Column getting updated

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• vignesh m

we are doing pass by reference hence values are updated , check signature below

``` ```
bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
``` ```
• proxhotdog

I have ported this code in ruby and it said stack level too deep (SystemStackError)

• abc

why row-row%3

• abc

Sorry understood!

• mani

I don’t understand. can u please explain ?

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• mahesh

Incase the UNASSIGNED number is 5th row we need to check if the num fits in the 3*3 block.

5 – 5%3 = 5 – 2 = 3 (starting row of that 3*3 block)

take for example we are updating in 8th row

8 – 8%3 = 8 – 2 = 6 (starting row of that 3*3 block). Beautiful thinking .

• Venki

An interesting question would be “How can we assure that the given input is feasible?”. The situation faced by Sudoku game designers while drafting Easy, Medium and Hard puzzles.

Any thoughts on how can we ensure minimum input which can lead to a solution? Or sufficiency of input to lead a valid solution.

• Aashish

@Venki,
Bit vector can be used to ensure whether an input will
9 bits can be used to represent any of the digits from 1 to 9[we are talking about 9×9 Sudoku,right!].
To check whether a Cell is pre-filled & thus can’t be used for user input, it can be easily checked by ANDing the 9 bit vector with 511[2^9-1].If the result of AND operation is zero[none of the bit of the bit vector is set], the cell is empty.

The below structure can be handy.

``` ```
{
int bit:9;
};

``` ```

A 2D bit vector of size NxN[9 here] is needed to represent each cell.
The memory has thus reduced from 9x9x4 = 324 bytes[if bit vectors are not used] to
9x9x9/8 = 92 bytes.

Let me know if we can do better.

• Venki

Whether to represent the matrix as bit vector or boolean array, or int/char array, how does it matter? We will conserve space, but all are same.

My question is given a partially filled grid, how can we ensure that the user can successfully arrive at valid solution?

Putting in other words, generate all possible grid permutations. Now discard the invalid grids. From the remaining grids, take any grid. Gradually remove random elements one after another from this grid. How many such random deletions can be possible? Say, we left with N elements in the grid after 81-N deletions. Can we ensure that the user will be able to fill these deleted elements? What if we delete one more element, and left with N-1 elements on the grid. Now is it possible to fill it in?

There must be a criteria to design the puzzle. I am looking for more thoughts.

• Diksha
``` ```
#include <stdio.h>
#include <stdlib.h>
#define SIZE 9

int isValid(int (*sudoku)[SIZE],int row,int col,int weight)
{
int i,j,start_row,start_col;

for(i=0;i<SIZE;i++)
if(sudoku[row][i]==weight)
return 0;

for(i=0;i<SIZE;i++)
if(sudoku[i][col]==weight)
return 0;

start_row=(row/3)*3;
start_col=(col/3)*3;
for(i=start_row;i<start_row+3;i++)
for(j=start_col;j<start_col+3;j++)
if(sudoku[i][j]==weight)
return 0;

return 1;
}

void printSolution(int (*sudoku)[SIZE])
{
int i,j;
printf("....................................\n");
for(i=0;i<SIZE;i++)
{
for(j=0;j<SIZE;j++)
printf("%d ",sudoku[i][j]);
printf("\n");
}
printf("....................................\n");
}

void solveSudoku(int (*sudoku)[SIZE],int row,int col)
{
int i;
if(row==SIZE && col==0)
printSolution(sudoku);
else
{
if(sudoku[row][col])    //encounters a pre-filled cell.
{
solveSudoku(sudoku,row,col+1);

if(col==SIZE-1)
solveSudoku(sudoku,row+1,0);
}
else
for(i=1;i<=SIZE;i++)
if( isValid(sudoku,row,col,i) )
{
sudoku[row][col]=i;

solveSudoku(sudoku,row,col+1);

if(col==SIZE-1)
solveSudoku(sudoku,row+1,0);

sudoku[row][col]=0;
}
}
}

int main()
{
int sudoku[SIZE][SIZE]={{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 i,j;

printSolution(sudoku);  //Display inputted sudoku from the file

solveSudoku(sudoku,0,0);

return 0;
}
``` ```

See output here: http://ideone.com/8YZ4z

• Subin

Nice Code. Its working fine for me.
only you have to handle col variable from going into array index out of bounds error which can be handled with one simple if case….

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• jinzhi chen

very nice. thanks

• varun

What should be the complexity for this algo..

Let’s say total empty columns are n then I think complexity should be 9^n because for each empty box maximum tries should be 9 (1…9).

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• kartik

Yes, it should be 9^n in worst case.

• Diksha

Are you sure the time complexity is 9^n.
AFAIT, each empty slot can be filled in 9 ways.
So, the time complexity should be (no. of empty slots)^9.

Let me know if i am missing anything.

• Diksha

Sorry, i misunderstood, it would be
9^(no. of empty slots)

• charan

Its very explanatory. thanks for sharing

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Zheng Luo

Very Nice Code. Thanks for sharing