From 1b856e92c51d7fc27ccda7264be255d302a35eaf Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 19:52:11 +0500 Subject: [PATCH 01/11] homework02 complete --- homework02/sudoku.py | 83 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index df78ab1..6032c70 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -1,5 +1,6 @@ import pathlib import typing as tp +import random T = tp.TypeVar("T") @@ -38,12 +39,16 @@ 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]] + [[1, 2], [3, 4]]) >>> group([1,2,3,4,5,6,7,8,9], 3) [[1, 2, 3], [4, 5, 6], [7, 8, 9]] """ - pass - + a = [] + i = 0 + for j in range(n, len(values) + 1, n): + a.append(values[i:j]) + i = j + return a def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: """Возвращает все значения для номера строки, указанной в pos @@ -55,7 +60,7 @@ def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str >>> get_row([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']], (2, 0)) ['.', '8', '9'] """ - pass + return(grid[pos[0]]) def get_col(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: @@ -68,7 +73,10 @@ def get_col(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str >>> get_col([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']], (0, 2)) ['3', '6', '9'] """ - pass + column = [] + for i in range(len(grid)): + column.append(grid[i][pos[1]]) + return column def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: @@ -82,7 +90,13 @@ def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[s >>> get_block(grid, (8, 8)) ['2', '8', '.', '.', '.', '5', '.', '7', '9'] """ - pass + block = [] + number_of_string = pos[0] // 3 + number_of_column = pos[1] // 3 + for i in range(number_of_string * 3, number_of_string * 3 + 3): + for j in range(number_of_column * 3, number_of_column * 3 + 3): + block.append(grid[i][j]) + return block def find_empty_positions(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.Tuple[int, int]]: @@ -95,7 +109,14 @@ def find_empty_positions(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.Tuple[in >>> find_empty_positions([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']]) (2, 0) """ - pass + x = -1 + for i in grid: + y = -1 + x += 1 + for j in i: + y += 1 + if j == ".": + return x, y def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.Set[str]: @@ -109,7 +130,14 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) - >>> values == {'2', '5', '9'} True """ - pass + numbers = set("123456789") + string = set(get_row(grid, pos)) + column = set(get_col(grid, pos)) + block = set(get_block(grid, pos)) + numbers -= string + numbers -= column + numbers -= block + return numbers def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]: @@ -125,13 +153,32 @@ def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]: >>> 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']] """ - pass - + pos = find_empty_positions(grid) + if pos is None: + return grid + else: + possible_values = find_possible_values(grid, pos) + for number in possible_values: + grid[pos[0]][pos[1]] = number + res = solve(grid) + if res: + return res + grid[pos[0]][pos[1]] = "." def check_solution(solution: tp.List[tp.List[str]]) -> bool: """ Если решение solution верно, то вернуть True, в противном случае False """ # TODO: Add doctests with bad puzzles - pass + arr = ["1", "2", "3", "4", "5", "6", "7", "8", "9"] + for i in range(0, len(solution)): + for j in range(0, len(solution)): + pos = i, j + if not ( + arr == sorted(get_row(solution, pos)) + and arr == sorted(get_col(solution, pos)) + and arr == sorted(get_block(solution, pos)) + ): + return False + return True def generate_sudoku(N: int) -> tp.List[tp.List[str]]: @@ -156,7 +203,14 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]: >>> check_solution(solution) True """ - pass + grid = [["." for _ in range(9)] for _ in range(9)] + if N > 81: + N = 81 + dots = random.sample([i for i in range(81)], 81 - N) + solve(grid) + for elem in dots: + grid[elem // 9][elem % 9] = "." + return grid if __name__ == "__main__": @@ -168,3 +222,8 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]: print(f"Puzzle {fname} can't be solved") else: display(solution) + if check_solution(solution): + print("Solution is correct") + else: + print("LoL") + display(generate_sudoku(1)) \ No newline at end of file From f37d8557811b871ce24df9bb0b9de4e387cb20c6 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 19:53:34 +0500 Subject: [PATCH 02/11] homework02 complete --- .github/workflows/cs102.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cs102.yml b/.github/workflows/cs102.yml index 4509ac4..cb286a1 100644 --- a/.github/workflows/cs102.yml +++ b/.github/workflows/cs102.yml @@ -10,7 +10,7 @@ jobs: - name: Set up Python 3.8.6 uses: actions/setup-python@v2 with: - python-version: '3.8.6' + python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip From dd52721cd37370487597c37d515c0cce805c8b1d Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 19:55:12 +0500 Subject: [PATCH 03/11] homework02 complete --- homework02/sudoku.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 6032c70..a34480c 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -1,6 +1,7 @@ import pathlib -import typing as tp import random +import typing as tp + T = tp.TypeVar("T") From e055df02dd6744642aeabe1475174caafb4b9db5 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 19:57:15 +0500 Subject: [PATCH 04/11] homework02 complete --- homework02/sudoku.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index a34480c..b1faed4 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -2,7 +2,6 @@ import random import typing as tp - T = tp.TypeVar("T") From b2e1d2a6d124aaa511a44fa5be5c95cbe253be6e Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 19:58:53 +0500 Subject: [PATCH 05/11] homework02 complete --- homework02/sudoku.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index b1faed4..a8b1548 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -6,7 +6,7 @@ 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 +20,7 @@ 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): @@ -60,7 +60,7 @@ def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str >>> get_row([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']], (2, 0)) ['.', '8', '9'] """ - return(grid[pos[0]]) + return grid[pos[0]] def get_col(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: From 570c7e738e58f715235af3c2ab9c47af93af9192 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 20:02:18 +0500 Subject: [PATCH 06/11] homework02 complete --- homework02/sudoku.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index a8b1548..2bbab7d 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -141,7 +141,7 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) - def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]: - """ Решение пазла, заданного в grid """ + """Решение пазла, заданного в grid""" """ Как решать Судоку? 1. Найти свободную позицию 2. Найти все возможные значения, которые могут находиться на этой позиции @@ -166,16 +166,16 @@ def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]: grid[pos[0]][pos[1]] = "." def check_solution(solution: tp.List[tp.List[str]]) -> bool: - """ Если решение solution верно, то вернуть True, в противном случае False """ + """Если решение solution верно, то вернуть True, в противном случае False""" # TODO: Add doctests with bad puzzles arr = ["1", "2", "3", "4", "5", "6", "7", "8", "9"] for i in range(0, len(solution)): for j in range(0, len(solution)): pos = i, j if not ( - arr == sorted(get_row(solution, pos)) - and arr == sorted(get_col(solution, pos)) - and arr == sorted(get_block(solution, pos)) + arr == sorted(get_row(solution, pos)) + and arr == sorted(get_col(solution, pos)) + and arr == sorted(get_block(solution, pos)) ): return False return True @@ -226,4 +226,4 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]: print("Solution is correct") else: print("LoL") - display(generate_sudoku(1)) \ No newline at end of file + display(generate_sudoku(1)) \ No newline at end of file From fb07cc4ca5da7e87ab0d17684099b416174261f3 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 20:05:03 +0500 Subject: [PATCH 07/11] homework02 complete --- homework02/sudoku.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 2bbab7d..7c02bed 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -50,6 +50,7 @@ def group(values: tp.List[T], n: int) -> tp.List[tp.List[T]]: i = j return a + def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: """Возвращает все значения для номера строки, указанной в pos @@ -165,6 +166,7 @@ def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]: return res grid[pos[0]][pos[1]] = "." + def check_solution(solution: tp.List[tp.List[str]]) -> bool: """Если решение solution верно, то вернуть True, в противном случае False""" # TODO: Add doctests with bad puzzles @@ -226,4 +228,4 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]: print("Solution is correct") else: print("LoL") - display(generate_sudoku(1)) \ No newline at end of file + display(generate_sudoku(1)) From cbc4a2d0f4152ae478db8f25396c624a86ef89c1 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Thu, 9 Mar 2023 20:10:07 +0500 Subject: [PATCH 08/11] homework02 complete --- homework02/sudoku.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 7c02bed..1118752 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -100,7 +100,7 @@ def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[s return block -def find_empty_positions(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.Tuple[int, int]]: +def find_empty_positions(grid: tp.List[tp.List[str]]): """Найти первую свободную позицию в пазле >>> find_empty_positions([['1', '2', '.'], ['4', '5', '6'], ['7', '8', '9']]) @@ -141,7 +141,7 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) - return numbers -def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]: +def solve(grid: tp.List[tp.List[str]]): """Решение пазла, заданного в grid""" """ Как решать Судоку? 1. Найти свободную позицию From 3b778cf77757c076ab022fb0cb15a704dbc1e888 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Fri, 10 Mar 2023 04:37:00 +0500 Subject: [PATCH 09/11] homework02 complete --- homework02/sudoku.py | 97 ++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 1118752..66be4e1 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -43,12 +43,14 @@ def group(values: tp.List[T], n: int) -> tp.List[tp.List[T]]: >>> group([1,2,3,4,5,6,7,8,9], 3) [[1, 2, 3], [4, 5, 6], [7, 8, 9]] """ - a = [] i = 0 - for j in range(n, len(values) + 1, n): - a.append(values[i:j]) + j = n + s = [] + while j <= len(values): + s.append(values[i:j]) i = j - return a + j += n + return s def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: @@ -74,10 +76,10 @@ def get_col(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str >>> get_col([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']], (0, 2)) ['3', '6', '9'] """ - column = [] + post = [] for i in range(len(grid)): - column.append(grid[i][pos[1]]) - return column + post.append(grid[i][pos[1]]) + return post def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]: @@ -91,13 +93,11 @@ def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[s >>> get_block(grid, (8, 8)) ['2', '8', '.', '.', '.', '5', '.', '7', '9'] """ - block = [] - number_of_string = pos[0] // 3 - number_of_column = pos[1] // 3 - for i in range(number_of_string * 3, number_of_string * 3 + 3): - for j in range(number_of_column * 3, number_of_column * 3 + 3): - block.append(grid[i][j]) - return block + square = [] + for i in range(pos[0] // 3 * 3, pos[0] // 3 * 3 + 3): + for j in range(pos[1] // 3 * 3, pos[1] // 3 * 3 + 3): + square.append(grid[i][j]) + return square def find_empty_positions(grid: tp.List[tp.List[str]]): @@ -110,14 +110,14 @@ def find_empty_positions(grid: tp.List[tp.List[str]]): >>> find_empty_positions([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']]) (2, 0) """ - x = -1 - for i in grid: - y = -1 + x = - 1 + for i in range(len(grid)): x += 1 - for j in i: - y += 1 - if j == ".": + y = 0 + for j in range(len(grid[i])): + if grid[i][j] == ".": return x, y + y += 1 def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.Set[str]: @@ -131,14 +131,9 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) - >>> values == {'2', '5', '9'} True """ - numbers = set("123456789") - string = set(get_row(grid, pos)) - column = set(get_col(grid, pos)) - block = set(get_block(grid, pos)) - numbers -= string - numbers -= column - numbers -= block - return numbers + full = set(get_row(grid, pos) + get_col(grid, pos) + get_block(grid, pos)) + possible_values = set("123456789") - full + return possible_values def solve(grid: tp.List[tp.List[str]]): @@ -154,31 +149,27 @@ def solve(grid: tp.List[tp.List[str]]): >>> 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']] """ - pos = find_empty_positions(grid) - if pos is None: + empty_positions = find_empty_positions(grid) + if empty_positions is None: return grid else: - possible_values = find_possible_values(grid, pos) - for number in possible_values: - grid[pos[0]][pos[1]] = number - res = solve(grid) - if res: - return res - grid[pos[0]][pos[1]] = "." + possible_values = find_possible_values(grid, empty_positions) + for i in possible_values: + grid[empty_positions[0]][empty_positions[1]] = i + next = solve(grid) + if next: + return next + grid[empty_positions[0]][empty_positions[1]] = '.' def check_solution(solution: tp.List[tp.List[str]]) -> bool: """Если решение solution верно, то вернуть True, в противном случае False""" # TODO: Add doctests with bad puzzles - arr = ["1", "2", "3", "4", "5", "6", "7", "8", "9"] + all = ["1", "2", "3", "4", "5", "6", "7", "8", "9"] for i in range(0, len(solution)): for j in range(0, len(solution)): pos = i, j - if not ( - arr == sorted(get_row(solution, pos)) - and arr == sorted(get_col(solution, pos)) - and arr == sorted(get_block(solution, pos)) - ): + if not sorted(get_row(solution, pos)) == all or not sorted(get_col(solution, pos)) == all or not sorted(get_block(solution, pos)) == all: return False return True @@ -205,13 +196,23 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]: >>> check_solution(solution) True """ - grid = [["." for _ in range(9)] for _ in range(9)] + grid = [["." for i in range(9)] for i in range(9)] + print(N) if N > 81: N = 81 - dots = random.sample([i for i in range(81)], 81 - N) - solve(grid) - for elem in dots: - grid[elem // 9][elem % 9] = "." + print(grid) + grid = solve(grid) + print(grid) + k = 0 + while k != 81 - N: + i = random.randint(0, 8) + j = random.randint(0, 8) + if grid[i][j] == ".": + k = k + else: + grid[i][j] = "." + k += 1 + print(grid) return grid From fb26868b96fe344a7ee27e1efe405dd9c9f1beba Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Fri, 10 Mar 2023 04:42:01 +0500 Subject: [PATCH 10/11] homework02 complete --- homework02/sudoku.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 66be4e1..282ad0a 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -110,7 +110,7 @@ def find_empty_positions(grid: tp.List[tp.List[str]]): >>> find_empty_positions([['1', '2', '3'], ['4', '5', '6'], ['.', '8', '9']]) (2, 0) """ - x = - 1 + x = -1 for i in range(len(grid)): x += 1 y = 0 @@ -159,7 +159,7 @@ def solve(grid: tp.List[tp.List[str]]): next = solve(grid) if next: return next - grid[empty_positions[0]][empty_positions[1]] = '.' + grid[empty_positions[0]][empty_positions[1]] = "." def check_solution(solution: tp.List[tp.List[str]]) -> bool: @@ -169,7 +169,11 @@ def check_solution(solution: tp.List[tp.List[str]]) -> bool: for i in range(0, len(solution)): for j in range(0, len(solution)): pos = i, j - if not sorted(get_row(solution, pos)) == all or not sorted(get_col(solution, pos)) == all or not sorted(get_block(solution, pos)) == all: + if ( + not sorted(get_row(solution, pos)) == all + or not sorted(get_col(solution, pos)) == all + or not sorted(get_block(solution, pos)) == all: + ): return False return True From d621fd1bf0c95d740a32ffc0e0622e8af5900fa6 Mon Sep 17 00:00:00 2001 From: NinjaTurtleWOW Date: Fri, 10 Mar 2023 04:43:48 +0500 Subject: [PATCH 11/11] homework02 complete --- homework02/sudoku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework02/sudoku.py b/homework02/sudoku.py index 282ad0a..df02ea2 100644 --- a/homework02/sudoku.py +++ b/homework02/sudoku.py @@ -172,7 +172,7 @@ def check_solution(solution: tp.List[tp.List[str]]) -> bool: if ( not sorted(get_row(solution, pos)) == all or not sorted(get_col(solution, pos)) == all - or not sorted(get_block(solution, pos)) == all: + or not sorted(get_block(solution, pos)) == all ): return False return True