Skip to content

Added sudoku solving program in backtracking algorithms #1128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 13, 2019
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions backtracking/sudoku.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@

'''

Given a partially filled 9×9 2D array, the objective is to fill a 9×9
square grid with digits numbered 1 to 9, so that every row, column, and
and each of the nine 3×3 sub-grids contains all of the digits.

This can be solved using Backtracking and is similar to n-queens.
We check to see if a cell is safe or not and recursively call the
function on the next column to see if it returns True. if yes, we
have solved the puzzle. else, we backtrack and place another number
in that cell and repeat this process.

'''

# assigning initial values to the grid
initial_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]]
# a grid with no solution
no_solution = [[5,0,6,5,0,8,4,0,3],
[5,2,0,0,0,0,0,0,2],
[1,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]]

def is_safe(grid, row, column, n):
'''
This function checks the grid to see if each row,
column, and the 3x3 subgrids contain the digit 'n'.
It returns False if it is not 'safe' (a duplicate digit
is found) else returns True if it is 'safe'

'''

for i in range(9):
if grid[row][i] == n:
return False

for i in range(9):
if grid[i][column] == n:
return False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OPTIONAL: Would it be possible to compress lines 46-52 onto just three lines?


for i in range(3):
for j in range(3):
if grid[(row - row%3) + i][(column - column%3) + j] == n:
return False

return True


def is_completed(grid):
'''
This function checks if the puzzle is completed or not.
it is completed when all the cells are assigned with a number(not zero)
and There is no repeating number in any column, row or 3x3 subgrid.

'''

for row in grid:
for cell in row:
if cell == 0:
return False

return True
Copy link
Member

@cclauss cclauss Aug 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OPTIONAL: Challenges:

  1. Try to do this without hardcoding 9 and without using range() like: for row in grid: for cell in row:
  2. Try making the body of this function a one-liner using nested list comprehensions.



def find_empty_location(grid):
'''
This function finds an empty location so that we can assign a number
for that particular row and column.

'''

for i in range(9):
for j in range(9):
if grid[i][j] == 0:
return i, j


def sudoku(grid):
'''
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)

'''

if is_completed(grid):
return True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return grid


row, column = find_empty_location(grid)

for digit in range(1, 10):
if is_safe(grid, row, column, digit):
grid[row][column] = digit

if sudoku(grid):
return grid

grid[row][column] = 0

return False


def print_solution(grid):
'''
A function to print the solution in the form
of a 9x9 grid

'''

for row in grid:
for cell in row:
print(cell, end = ' ')
print()


if __name__ == '__main__':

# make a copy of grid so that you can compare with the unmodified grid
grid1 = list(map(list, initial_grid))
grid2 = list(map(list, no_solution))
ans1 = sudoku(grid1)
ans2 = sudoku(grid2)
if ans1:
print('grid after solving:\n')
print_solution(ans1)
else:
print('Cannot find a solution')