diff --git a/.github/workflows/cs102.yml b/.github/workflows/cs102.yml
index 4509ac4..8e1e8be 100644
--- a/.github/workflows/cs102.yml
+++ b/.github/workflows/cs102.yml
@@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Set up Python 3.8.6
+ - name: Set up Python 3.10.7
uses: actions/setup-python@v2
with:
- python-version: '3.8.6'
+ python-version: '3.10.7'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..b15c5a4
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+sudoku.py
\ No newline at end of file
diff --git a/.idea/Chzh.iml b/.idea/Chzh.iml
new file mode 100644
index 0000000..8e5446a
--- /dev/null
+++ b/.idea/Chzh.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..cc2518d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..adbc062
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1673962365428
+
+
+ 1673962365428
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/main.py
+ 8
+
+
+
+
+
+
\ No newline at end of file
diff --git a/homework02/sudoku.py b/homework02/sudoku.py
index df78ab1..87139b0 100644
--- a/homework02/sudoku.py
+++ b/homework02/sudoku.py
@@ -1,11 +1,12 @@
import pathlib
+import random
import typing as tp
T = tp.TypeVar("T")
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()
@@ -19,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):
@@ -42,7 +43,16 @@ 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]]
"""
- pass
+ t: tp.List[T] = []
+ res = []
+ length = len(values)
+ for i in range(length):
+ if i % n == 0 and i != 0:
+ res.append(t)
+ t = []
+ t.append(values[i])
+ res.append(t)
+ return res
def get_row(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]:
@@ -55,7 +65,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 +78,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
+ res = []
+ for arr in grid:
+ res.append(arr[pos[1]])
+ return res
def get_block(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.List[str]:
@@ -82,10 +95,16 @@ 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
+ res = []
+ r = pos[0] // 3 * 3
+ c = pos[1] // 3 * 3
+ for i in range(r, r + 3):
+ for j in range(c, c + 3):
+ res.append(grid[i][j])
+ return res
-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]]) -> tp.Tuple[int, int]:
"""Найти первую свободную позицию в пазле
>>> find_empty_positions([['1', '2', '.'], ['4', '5', '6'], ['7', '8', '9']])
@@ -95,7 +114,13 @@ 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
+ if grid != 0:
+ for i in range(len(grid)):
+ for j in range(len(grid[i])):
+ if not grid[i][j].isdigit():
+ r, c = i, j
+ return r, c
+ return -1, -1
def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -> tp.Set[str]:
@@ -109,11 +134,20 @@ def find_possible_values(grid: tp.List[tp.List[str]], pos: tp.Tuple[int, int]) -
>>> values == {'2', '5', '9'}
True
"""
- pass
+ res = []
+ for arr in range(1, 10):
+ s = str(arr)
+ if (
+ s not in get_block(grid, pos)
+ and s not in get_col(grid, pos)
+ and s not in get_row(grid, pos)
+ ):
+ res.append(s)
+ return set(res)
def solve(grid: tp.List[tp.List[str]]) -> tp.Optional[tp.List[tp.List[str]]]:
- """ Решение пазла, заданного в grid """
+ """Решение пазла, заданного в grid"""
""" Как решать Судоку?
1. Найти свободную позицию
2. Найти все возможные значения, которые могут находиться на этой позиции
@@ -125,13 +159,36 @@ 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
+ empty = find_empty_positions(grid) # type: tp.Tuple[int, int]
+ if empty[0] < 0:
+ return grid
+ possible = find_possible_values(grid, empty) # type: tp.Set[str]
+ if not possible:
+ return None
+ for i in possible:
+ grid[empty[0]][empty[1]] = i
+ if solve(grid):
+ return grid
+ grid[empty[0]][empty[1]] = "."
+ return None
def check_solution(solution: tp.List[tp.List[str]]) -> bool:
- """ Если решение solution верно, то вернуть True, в противном случае False """
+ """Если решение solution верно, то вернуть True, в противном случае False"""
# TODO: Add doctests with bad puzzles
- pass
+ g = solution
+ for i in range(9):
+ if len(get_row(g, (i, 0))) != len(set(get_row(g, (i, 0)))) or len(
+ get_col(g, (0, i))
+ ) != len(set(get_col(g, (0, i)))):
+ return False
+ if i == 0 or i == 3 or i == 6:
+ for j in range(0, 9, 3):
+ if len(get_block(g, (i, j))) != len(set(get_block(g, (i, j)))):
+ return False
+ if "." in g[i]:
+ return False
+ return True
def generate_sudoku(N: int) -> tp.List[tp.List[str]]:
@@ -156,7 +213,15 @@ def generate_sudoku(N: int) -> tp.List[tp.List[str]]:
>>> check_solution(solution)
True
"""
- pass
+ grid = [["."] * 9 for _ in range(9)]
+ solve(grid)
+ count, N = 0, min(81, N)
+ while count < 81 - N:
+ i, j = random.randint(0, 8), random.randint(0, 8)
+ if grid[i][j] != ".":
+ grid[i][j] = "."
+ count += 1
+ return grid
if __name__ == "__main__":
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..5596b44
--- /dev/null
+++ b/main.py
@@ -0,0 +1,16 @@
+# This is a sample Python script.
+
+# Press Shift+F10 to execute it or replace it with your code.
+# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
+
+
+def print_hi(name):
+ # Use a breakpoint in the code line below to debug your script.
+ print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
+
+
+# Press the green button in the gutter to run the script.
+if __name__ == '__main__':
+ print_hi('PyCharm')
+
+# See PyCharm help at https://www.jetbrains.com/help/pycharm/