[mypy] Add/fix type annotations for backtracking algorithms (#4055)

* Fix mypy errors for backtracking algorithms

* Fix CI failure
This commit is contained in:
Dhruv Manilawala
2020-12-24 18:16:21 +05:30
committed by GitHub
parent 0ccb213c11
commit f3ba9b6c50
7 changed files with 101 additions and 109 deletions

View File

@ -1,20 +1,20 @@
from typing import List, Tuple, Union
"""
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.
"""
from typing import List, Optional, Tuple
Matrix = List[List[int]]
"""
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 = [
initial_grid: Matrix = [
[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],
@ -27,7 +27,7 @@ initial_grid = [
]
# a grid with no solution
no_solution = [
no_solution: Matrix = [
[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],
@ -80,7 +80,7 @@ def is_completed(grid: Matrix) -> bool:
return all(all(cell != 0 for cell in row) for row in grid)
def find_empty_location(grid: Matrix) -> Tuple[int, int]:
def find_empty_location(grid: Matrix) -> Optional[Tuple[int, int]]:
"""
This function finds an empty location so that we can assign a number
for that particular row and column.
@ -89,9 +89,10 @@ def find_empty_location(grid: Matrix) -> Tuple[int, int]:
for j in range(9):
if grid[i][j] == 0:
return i, j
return None
def sudoku(grid: Matrix) -> Union[Matrix, bool]:
def sudoku(grid: Matrix) -> Optional[Matrix]:
"""
Takes a partially filled-in grid and attempts to assign values to
all unassigned locations in such a way to meet the requirements
@ -107,25 +108,30 @@ def sudoku(grid: Matrix) -> Union[Matrix, bool]:
[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]]
>>> sudoku(no_solution)
False
>>> sudoku(no_solution) is None
True
"""
if is_completed(grid):
return grid
row, column = find_empty_location(grid)
location = find_empty_location(grid)
if location is not None:
row, column = location
else:
# If the location is ``None``, then the grid is solved.
return grid
for digit in range(1, 10):
if is_safe(grid, row, column, digit):
grid[row][column] = digit
if sudoku(grid):
if sudoku(grid) is not None:
return grid
grid[row][column] = 0
return False
return None
def print_solution(grid: Matrix) -> None:
@ -141,11 +147,12 @@ def print_solution(grid: Matrix) -> None:
if __name__ == "__main__":
# make a copy of grid so that you can compare with the unmodified grid
for grid in (initial_grid, no_solution):
grid = list(map(list, grid))
solution = sudoku(grid)
if solution:
print("grid after solving:")
for example_grid in (initial_grid, no_solution):
print("\nExample grid:\n" + "=" * 20)
print_solution(example_grid)
print("\nExample grid solution:")
solution = sudoku(example_grid)
if solution is not None:
print_solution(solution)
else:
print("Cannot find a solution.")