From b9babeb735b0dd2c1f2cdac7dcb2d889b28a0709 Mon Sep 17 00:00:00 2001 From: 857l <61349357+857l@users.noreply.github.com> Date: Mon, 7 Nov 2022 11:45:21 +0300 Subject: [PATCH 1/6] Update sudoku.py --- homework02/sudoku.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 3367575..0823879 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -4,7 +4,6 @@ T = tp.TypeVar("T") - def read_sudoku(path: tp.Union[str, pathlib.Path]) -> tp.List[tp.List[str]]: """Прочитать Судоку из указанного файла""" path = pathlib.Path(path) From 1217bbaa6297771728a1fc823d3bddbd314b12f5 Mon Sep 17 00:00:00 2001 From: 857l <61349357+857l@users.noreply.github.com> Date: Mon, 7 Nov 2022 11:46:26 +0300 Subject: [PATCH 2/6] Update sudoku.py --- homework02/sudoku.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 0823879..3367575 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -4,6 +4,7 @@ T = tp.TypeVar("T") + def read_sudoku(path: tp.Union[str, pathlib.Path]) -> tp.List[tp.List[str]]: """Прочитать Судоку из указанного файла""" path = pathlib.Path(path) From 6cdd63544e85cf9cb9529f9ff36acc79b2ce0a70 Mon Sep 17 00:00:00 2001 From: 857l <61349357+857l@users.noreply.github.com> Date: Wed, 9 Nov 2022 18:17:29 +0300 Subject: [PATCH 3/6] Update sudoku.py --- homework02/sudoku.py | 123 ++++++------------------------------------- 1 file changed, 16 insertions(+), 107 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 3367575..3498509 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -6,7 +6,6 @@ def read_sudoku(path: tp.Union[str, pathlib.Path]) -> tp.List[tp.List[str]]: - """Прочитать Судоку из указанного файла""" path = pathlib.Path(path) with path.open() as f: puzzle = f.read() @@ -20,7 +19,6 @@ def create_grid(puzzle: str) -> tp.List[tp.List[str]]: def display(grid: tp.List[tp.List[str]]) -> None: - """Вывод Судоку""" width = 2 line = "+".join(["-" * (width * 3)] * 3) for row in range(9): @@ -35,14 +33,6 @@ def display(grid: tp.List[tp.List[str]]) -> None: def group(values: tp.List[T], n: int) -> tp.List[tp.List[T]]: - """ - Сгруппировать значения values в список, состоящий из списков по n элементов - - >>> group([1,2,3,4], 2) - [[1, 2], [3, 4]] - >>> group([1,2,3,4,5,6,7,8,9], 3) - [[1, 2, 3], [4, 5, 6], [7, 8, 9]] - """ ans = [] for i in range(0, len(values), n): ans.append(values[i : i + n]) @@ -51,28 +41,10 @@ def group(values: tp.List[T], n: int) -> tp.List[tp.List[T]]: def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: - """Возвращает все значения для номера строки, указанной в pos - - >>> get_row([['1', '2', '.'], ['4', '5', '6'], ['7', '8', '9']], (0, 0)) - ['1', '2', '.'] - >>> get_row([['1', '2', '3'], ['4', '.', '6'], ['7', '8', '9']], (1, 0)) - ['4', '.', '6'] - >>> get_row([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']], (2, 0)) - ['.', '8', '9'] - """ return grid[pos[0]] def get_col(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: - """Возвращает все значения для номера столбца, указанного в pos - - >>> get_col([['1', '2', '.'], ['4', '5', '6'], ['7', '8', '9']], (0, 0)) - ['1', '4', '7'] - >>> get_col([['1', '2', '3'], ['4', '.', '6'], ['7', '8', '9']], (0, 1)) - ['2', '.', '8'] - >>> get_col([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']], (0, 2)) - ['3', '6', '9'] - """ ans = [] for item in grid: ans.append(item[pos[1]]) @@ -81,16 +53,6 @@ def get_col(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: - """Возвращает все значения из квадрата, в который попадает позиция pos - - >>> grid = read_sudoku('puzzle1.txt') - >>> get_block(grid, (0, 1)) - ['5', '3', '.', '6', '.', '.', '.', '9', '8'] - >>> get_block(grid, (4, 7)) - ['.', '.', '3', '.', '.', '1', '.', '.', '6'] - >>> get_block(grid, (8, 8)) - ['2', '8', '.', '.', '.', '5', '.', '7', '9'] - """ ans = [] pos_y = pos[0] // 3 * 3 pos_x = pos[1] // 3 * 3 @@ -101,16 +63,6 @@ def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[s def find_empty_positions(grid: tp.List[tp.List[str]]) -> tp.Tuple[int, int]: - """Найти первую свободную позицию в пазле - - >>> find_empty_positions([['1', '2', '.'], ['4', '5', '6'], ['7', '8', '9']]) - (0, 2) - >>> find_empty_positions([['1', '2', '3'], ['4', '.', '6'], ['7', '8', '9']]) - (1, 1) - >>> find_empty_positions([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']]) - (2, 0) - """ - for i in range(len(grid)): for j in range(len(grid[i])): if grid[i][j] == ".": @@ -120,17 +72,6 @@ def find_empty_positions(grid: tp.List[tp.List[str]]) -> tp.Tuple[int, int]: def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.Set[str]: - """Вернуть множество возможных значения для указанной позиции - - >>> grid = read_sudoku('puzzle1.txt') - >>> values = find_possible_values(grid, (0,2)) - >>> values == {'1', '2', '4'} - True - >>> values = find_possible_values(grid, (4,7)) - >>> values == {'2', '5', '9'} - True - """ - possible_values = set("123456789") possible_values -= set(get_row(grid, pos)) possible_values -= set(get_col(grid, pos)) @@ -140,35 +81,20 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) - def solve(grid: tp.List[tp.List[str]]) -> tp.List[tp.List[str]]: - """Решение пазла, заданного в grid""" - """ Как решать Судоку? - 1. Найти свободную позицию - 2. Найти все возможные значения, которые могут находиться на этой позиции - 3. Для каждого возможного значения: - 3.1. Поместить это значение на эту позицию - 3.2. Продолжить решать оставшуюся часть пазла - - >>> grid = read_sudoku('puzzle1.txt') - >>> solve(grid) - [['5', '3', '4', '6', '7', '8', '9', '1', '2'], ['6', '7', '2', '1', '9', '5', '3', '4', '8'], ['1', '9', '8', '3', '4', '2', '5', '6', '7'], ['8', '5', '9', '7', '6', '1', '4', '2', '3'], ['4', '2', '6', '8', '5', '3', '7', '9', '1'], ['7', '1', '3', '9', '2', '4', '8', '5', '6'], ['9', '6', '1', '5', '3', '7', '2', '8', '4'], ['2', '8', '7', '4', '1', '9', '6', '3', '5'], ['3', '4', '5', '2', '8', '6', '1', '7', '9']] - """ - empty_position = find_empty_positions(grid) if empty_position == (-1, -1): return grid possible_values = find_possible_values(grid, empty_position) - new_grid = [i[:] for i in grid] for i in possible_values: - new_grid[empty_position[0]][empty_position[1]] = i - new_solve = solve(new_grid) + grid[empty_position[0]][empty_position[1]] = i + new_solve = solve(grid) if new_solve: return new_solve - return grid + grid[empty_position[0]][empty_position[1]] = "." + return None def check_solution(solution: tp.List[tp.List[str]]) -> bool: - """Если решение solution верно, то вернуть True, в противном случае False""" - # TODO: Add doctests with bad puzzles s = set("123456789") for i in range(len(solution) // 3): for j in range(len(solution) // 3): @@ -193,27 +119,6 @@ def check_solution(solution: tp.List[tp.List[str]]) -> bool: def generate_sudoku(N: int) -> tp.List[tp.List[str]]: - """Генерация судоку заполненного на N элементов - - >>> grid = generate_sudoku(40) - >>> sum(1 for row in grid for e in row if e == '.') - 41 - >>> solution = solve(grid) - >>> check_solution(solution) - True - >>> grid = generate_sudoku(1000) - >>> sum(1 for row in grid for e in row if e == '.') - 0 - >>> solution = solve(grid) - >>> check_solution(solution) - True - >>> grid = generate_sudoku(0) - >>> sum(1 for row in grid for e in row if e == '.') - 81 - >>> solution = solve(grid) - >>> check_solution(solution) - True - """ size_of_sudoku = 9 new_sudoku = [["."] * size_of_sudoku] * size_of_sudoku new_sudoku = solve(new_sudoku) @@ -230,11 +135,15 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]: if __name__ == "__main__": - for fname in ["puzzle1.txt", "puzzle2.txt", "puzzle3.txt", "hard_puzzles.txt"]: - grid = read_sudoku(fname) - display(grid) - solution = solve(grid) - if not solution: - print(f"Puzzle {fname} can't be solved") - else: - display(solution) + grid = [ + ["5", "3", ".", ".", "7", ".", ".", ".", "."], + ["6", ".", ".", "1", "9", "5", ".", ".", "."], + [".", "9", "8", ".", ".", ".", ".", "6", "."], + ["8", ".", ".", ".", "6", ".", ".", ".", "3"], + ["4", ".", ".", "8", ".", "3", ".", ".", "1"], + ["7", ".", ".", ".", "2", ".", ".", ".", "6"], + [".", "6", ".", ".", ".", ".", "2", "8", "."], + [".", ".", ".", "4", "1", "9", ".", ".", "5"], + [".", ".", ".", ".", "8", ".", ".", "7", "9"], + ] + print(solve(grid)) From c3aabe34b29c307cb153a4b72b0948f991cc71ea Mon Sep 17 00:00:00 2001 From: 857l <61349357+857l@users.noreply.github.com> Date: Thu, 10 Nov 2022 23:07:01 +0300 Subject: [PATCH 4/6] Update sudoku.py --- homework02/sudoku.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 3498509..bab2208 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -84,14 +84,18 @@ def solve(grid: tp.List[tp.List[str]]) -> tp.List[tp.List[str]]: empty_position = find_empty_positions(grid) if empty_position == (-1, -1): return grid - possible_values = find_possible_values(grid, empty_position) - for i in possible_values: - grid[empty_position[0]][empty_position[1]] = i - new_solve = solve(grid) - if new_solve: - return new_solve - grid[empty_position[0]][empty_position[1]] = "." - return None + else: + possible_values = find_possible_values(grid, empty_position) + if possible_values == None: + return grid + else: + for i in possible_values: + grid[empty_position[0]][empty_position[1]] = str(i) + grid = solve(grid) + if find_empty_positions(grid) == (-1, -1): + return grid + grid[empty_position[0]][empty_position[1]] = "." + return grid def check_solution(solution: tp.List[tp.List[str]]) -> bool: From 4a83e6ddf398e943c343b63515c7666bc8a3f210 Mon Sep 17 00:00:00 2001 From: 857l <61349357+857l@users.noreply.github.com> Date: Thu, 10 Nov 2022 23:08:04 +0300 Subject: [PATCH 5/6] Update sudoku.py --- homework02/sudoku.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index bab2208..bae5df0 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -80,22 +80,18 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) - return possible_values -def solve(grid: tp.List[tp.List[str]]) -> tp.List[tp.List[str]]: +def solve(grid: tp.List[tp.List[str]]): empty_position = find_empty_positions(grid) if empty_position == (-1, -1): return grid - else: - possible_values = find_possible_values(grid, empty_position) - if possible_values == None: - return grid - else: - for i in possible_values: - grid[empty_position[0]][empty_position[1]] = str(i) - grid = solve(grid) - if find_empty_positions(grid) == (-1, -1): - return grid - grid[empty_position[0]][empty_position[1]] = "." - return grid + possible_values = find_possible_values(grid, empty_position) + for i in possible_values: + grid[empty_position[0]][empty_position[1]] = i + new_solve = solve(grid) + if new_solve: + return new_solve + grid[empty_position[0]][empty_position[1]] = "." + return None def check_solution(solution: tp.List[tp.List[str]]) -> bool: From b66d0f8633ccfd86ed88d896e1526f9851603fe8 Mon Sep 17 00:00:00 2001 From: 857l <61349357+857l@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:18:22 +0300 Subject: [PATCH 6/6] Update sudoku.py --- homework02/sudoku.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index bae5df0..2fbe4c5 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -119,19 +119,17 @@ def check_solution(solution: tp.List[tp.List[str]]) -> bool: def generate_sudoku(N: int) -> tp.List[tp.List[str]]: - size_of_sudoku = 9 - new_sudoku = [["."] * size_of_sudoku] * size_of_sudoku - new_sudoku = solve(new_sudoku) - - N = 81 - N - for i in range(N): - while True: + grid = [["." for i in range(9)] for j in range(9)] + grid = solve(grid) + N = N if N <= 81 else 81 + for i in range(81 - N): + x = randint(0, 8) + y = randint(0, 8) + while grid[x][y] == ".": x = randint(0, 8) y = randint(0, 8) - if new_sudoku[x][y] != ".": - new_sudoku[x][y] = "." - break - return new_sudoku + grid[x][y] = "." + return grid if __name__ == "__main__":