Skip to content

Commit f3c0b13

Browse files
adithbharadwajcclauss
authored andcommitted
Added sudoku solving program in backtracking algorithms (TheAlgorithms#1128)
* Added sudoku solver in backtracking * Added sudoku solver program * Added sudoku solver * Added sudoku solver * Format with black, add doctests, cleanup main
1 parent dc2b575 commit f3c0b13

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

backtracking/sudoku.py

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
"""
2+
3+
Given a partially filled 9×9 2D array, the objective is to fill a 9×9
4+
square grid with digits numbered 1 to 9, so that every row, column, and
5+
and each of the nine 3×3 sub-grids contains all of the digits.
6+
7+
This can be solved using Backtracking and is similar to n-queens.
8+
We check to see if a cell is safe or not and recursively call the
9+
function on the next column to see if it returns True. if yes, we
10+
have solved the puzzle. else, we backtrack and place another number
11+
in that cell and repeat this process.
12+
13+
"""
14+
15+
# assigning initial values to the grid
16+
initial_grid = [
17+
[3, 0, 6, 5, 0, 8, 4, 0, 0],
18+
[5, 2, 0, 0, 0, 0, 0, 0, 0],
19+
[0, 8, 7, 0, 0, 0, 0, 3, 1],
20+
[0, 0, 3, 0, 1, 0, 0, 8, 0],
21+
[9, 0, 0, 8, 6, 3, 0, 0, 5],
22+
[0, 5, 0, 0, 9, 0, 6, 0, 0],
23+
[1, 3, 0, 0, 0, 0, 2, 5, 0],
24+
[0, 0, 0, 0, 0, 0, 0, 7, 4],
25+
[0, 0, 5, 2, 0, 6, 3, 0, 0],
26+
]
27+
# a grid with no solution
28+
no_solution = [
29+
[5, 0, 6, 5, 0, 8, 4, 0, 3],
30+
[5, 2, 0, 0, 0, 0, 0, 0, 2],
31+
[1, 8, 7, 0, 0, 0, 0, 3, 1],
32+
[0, 0, 3, 0, 1, 0, 0, 8, 0],
33+
[9, 0, 0, 8, 6, 3, 0, 0, 5],
34+
[0, 5, 0, 0, 9, 0, 6, 0, 0],
35+
[1, 3, 0, 0, 0, 0, 2, 5, 0],
36+
[0, 0, 0, 0, 0, 0, 0, 7, 4],
37+
[0, 0, 5, 2, 0, 6, 3, 0, 0],
38+
]
39+
40+
41+
def is_safe(grid, row, column, n):
42+
"""
43+
This function checks the grid to see if each row,
44+
column, and the 3x3 subgrids contain the digit 'n'.
45+
It returns False if it is not 'safe' (a duplicate digit
46+
is found) else returns True if it is 'safe'
47+
48+
"""
49+
50+
for i in range(9):
51+
if grid[row][i] == n or grid[i][column] == n:
52+
return False
53+
54+
for i in range(3):
55+
for j in range(3):
56+
if grid[(row - row % 3) + i][(column - column % 3) + j] == n:
57+
return False
58+
59+
return True
60+
61+
62+
def is_completed(grid):
63+
"""
64+
This function checks if the puzzle is completed or not.
65+
it is completed when all the cells are assigned with a number(not zero)
66+
and There is no repeating number in any column, row or 3x3 subgrid.
67+
68+
"""
69+
70+
for row in grid:
71+
for cell in row:
72+
if cell == 0:
73+
return False
74+
75+
return True
76+
77+
78+
def find_empty_location(grid):
79+
"""
80+
This function finds an empty location so that we can assign a number
81+
for that particular row and column.
82+
83+
"""
84+
85+
for i in range(9):
86+
for j in range(9):
87+
if grid[i][j] == 0:
88+
return i, j
89+
90+
91+
def sudoku(grid):
92+
"""
93+
Takes a partially filled-in grid and attempts to assign values to
94+
all unassigned locations in such a way to meet the requirements
95+
for Sudoku solution (non-duplication across rows, columns, and boxes)
96+
97+
>>> sudoku(initial_grid) # doctest: +NORMALIZE_WHITESPACE
98+
[[3, 1, 6, 5, 7, 8, 4, 9, 2],
99+
[5, 2, 9, 1, 3, 4, 7, 6, 8],
100+
[4, 8, 7, 6, 2, 9, 5, 3, 1],
101+
[2, 6, 3, 4, 1, 5, 9, 8, 7],
102+
[9, 7, 4, 8, 6, 3, 1, 2, 5],
103+
[8, 5, 1, 7, 9, 2, 6, 4, 3],
104+
[1, 3, 8, 9, 4, 7, 2, 5, 6],
105+
[6, 9, 2, 3, 5, 1, 8, 7, 4],
106+
[7, 4, 5, 2, 8, 6, 3, 1, 9]]
107+
>>> sudoku(no_solution)
108+
False
109+
"""
110+
111+
if is_completed(grid):
112+
return grid
113+
114+
row, column = find_empty_location(grid)
115+
116+
for digit in range(1, 10):
117+
if is_safe(grid, row, column, digit):
118+
grid[row][column] = digit
119+
120+
if sudoku(grid):
121+
return grid
122+
123+
grid[row][column] = 0
124+
125+
return False
126+
127+
128+
def print_solution(grid):
129+
"""
130+
A function to print the solution in the form
131+
of a 9x9 grid
132+
133+
"""
134+
135+
for row in grid:
136+
for cell in row:
137+
print(cell, end=" ")
138+
print()
139+
140+
141+
if __name__ == "__main__":
142+
143+
# make a copy of grid so that you can compare with the unmodified grid
144+
for grid in (initial_grid, no_solution):
145+
grid = list(map(list, grid))
146+
solution = sudoku(grid)
147+
if solution:
148+
print("grid after solving:")
149+
print_solution(solution)
150+
else:
151+
print("Cannot find a solution.")

0 commit comments

Comments
 (0)