1
1
mirror of https://github.com/theoludwig/programming-challenges.git synced 2024-12-08 00:45:29 +01:00

feat(solutions): add sudoku/python/function

This commit is contained in:
Divlo 2021-07-06 15:59:33 +02:00
parent 08ba65ad6e
commit face9ed698
No known key found for this signature in database
GPG Key ID: 185ED2F15F104E52
7 changed files with 241 additions and 0 deletions

View File

@ -0,0 +1,8 @@
class Cell:
def __init__(self, number: int, x: int, y: int) -> None:
self.number = number
self.x = x
self.y = y
def __repr__(self) -> str:
return str(self.number)

View File

@ -0,0 +1,32 @@
from typing import List
from Cell import Cell
class Grid:
def __init__(self, grid: List[List[int]]) -> None:
data: List[List[Cell]] = []
for x in range(len(grid)):
column: List[Cell] = []
for y in range(len(grid[x])):
column.append(Cell(grid[x][y], y, x))
data.append(column)
self.data = data
def __repr__(self) -> str:
result: str = '['
for y in range(len(self.data)):
result += '['
for x in range(len(self.data[y])):
result += str(self.get_cell(x, y).number)
is_last_x = x == (len(self.data[y]) - 1)
if not is_last_x:
result += ', '
result += ']'
is_last_y = y == len(self.data) - 1
if not is_last_y:
result += ',\n'
return result + ']'
def get_cell(self, x: int, y: int) -> Cell:
return self.data[y][x]

View File

@ -0,0 +1,3 @@
# sudoku/python/function
Created by [@Divlo](https://github.com/Divlo) on 6 July 2021.

View File

@ -0,0 +1,143 @@
from unittest import TestCase, main
from copy import deepcopy
from Cell import Cell
from Grid import Grid
from example import grid, grid_solved
class Sudoku:
def __init__(self, grid: Grid) -> None:
assert len(grid.data) == 9, 'Invalid Sudoku Grid'
assert len(grid.data[0]) == 9, 'Invalid Sudoku Grid'
self.grid = deepcopy(grid)
def __repr__(self) -> str:
result: str = '+' + '---+' * 9 + '\n'
for x in range(0, 9):
result += ('|' + ' {} {} {} |'*3).format(*
[y.number if y.number != 0 else ' ' for y in self.grid.data[x]])
result += '\n'
if x % 3 == 2:
result += '+' + '---+' * 9 + '\n'
else:
result += '+' + ' +' * 9 + '\n'
return result
def is_possible_x(self, cell: Cell, number: int) -> bool:
for x in range(0, 9):
if cell.number == number:
continue
elif self.grid.get_cell(x, cell.y).number == number:
return False
return True
def is_possible_y(self, cell: Cell, number: int) -> bool:
for y in range(0, 9):
if cell.number == number:
continue
elif self.grid.get_cell(cell.x, y).number == number:
return False
return True
def is_possible_square(self, cell: Cell, number: int) -> bool:
x_square_start = (cell.x // 3) * 3
y_square_start = (cell.y // 3) * 3
for x in range(0, 3):
for y in range(0, 3):
if cell.number == number:
continue
elif self.grid.get_cell(x_square_start + x, y_square_start + y).number == number:
return False
return True
def is_possible(self, cell: Cell, number: int) -> bool:
return self.is_possible_x(cell, number) and self.is_possible_y(cell, number) and self.is_possible_square(cell, number)
def is_solved(self) -> bool:
for y in range(0, 9):
for x in range(0, 9):
cell = self.grid.get_cell(x, y)
if cell.number == 0:
return False
if not self.is_possible(cell, cell.number):
return False
return True
def solve(self) -> None:
for y in range(0, 9):
for x in range(0, 9):
cell = self.grid.get_cell(x, y)
if cell.number == 0:
for number in range(1, 10):
if self.is_possible(cell, number):
cell.number = number
self.solve()
cell.number = 0
return
self.grid = deepcopy(self.grid)
class SudokuTest(TestCase):
def test_is_possible_x(self):
sudoku = Sudoku(grid)
self.assertFalse(sudoku.is_possible_x(grid.get_cell(2, 0), 5))
self.assertFalse(sudoku.is_possible_x(grid.get_cell(2, 0), 3))
self.assertFalse(sudoku.is_possible_x(grid.get_cell(2, 0), 7))
self.assertTrue(sudoku.is_possible_x(grid.get_cell(2, 0), 4))
self.assertTrue(sudoku.is_possible_x(grid.get_cell(2, 0), 6))
self.assertTrue(sudoku.is_possible_x(grid.get_cell(2, 0), 8))
self.assertTrue(sudoku.is_possible_x(grid.get_cell(2, 0), 1))
self.assertTrue(sudoku.is_possible_x(grid.get_cell(2, 0), 2))
self.assertTrue(sudoku.is_possible_x(grid.get_cell(2, 0), 9))
def test_is_possible_y(self):
sudoku = Sudoku(grid)
self.assertFalse(sudoku.is_possible_y(grid.get_cell(0, 2), 5))
self.assertTrue(sudoku.is_possible_y(grid.get_cell(0, 2), 3))
self.assertFalse(sudoku.is_possible_y(grid.get_cell(0, 2), 7))
self.assertTrue(sudoku.is_possible_y(grid.get_cell(0, 2), 1))
self.assertTrue(sudoku.is_possible_y(grid.get_cell(0, 2), 2))
self.assertFalse(sudoku.is_possible_y(grid.get_cell(0, 2), 4))
self.assertFalse(sudoku.is_possible_y(grid.get_cell(0, 2), 6))
self.assertFalse(sudoku.is_possible_y(grid.get_cell(0, 2), 8))
self.assertTrue(sudoku.is_possible_y(grid.get_cell(0, 2), 9))
def test_is_possible_square(self):
sudoku = Sudoku(grid)
self.assertFalse(sudoku.is_possible_square(grid.get_cell(0, 2), 3))
self.assertFalse(sudoku.is_possible_square(grid.get_cell(0, 2), 5))
self.assertFalse(sudoku.is_possible_square(grid.get_cell(0, 2), 6))
self.assertFalse(sudoku.is_possible_square(grid.get_cell(0, 2), 8))
self.assertFalse(sudoku.is_possible_square(grid.get_cell(0, 2), 9))
self.assertTrue(sudoku.is_possible_square(grid.get_cell(0, 2), 1))
self.assertTrue(sudoku.is_possible_square(grid.get_cell(0, 2), 2))
self.assertTrue(sudoku.is_possible_square(grid.get_cell(0, 2), 4))
self.assertTrue(sudoku.is_possible_square(grid.get_cell(0, 2), 7))
def test_is_possible(self):
sudoku = Sudoku(grid)
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 8))
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 1))
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 7))
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 9))
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 6))
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 4))
self.assertFalse(sudoku.is_possible(grid.get_cell(4, 6), 2))
self.assertTrue(sudoku.is_possible(grid.get_cell(4, 6), 3))
self.assertTrue(sudoku.is_possible(grid.get_cell(4, 6), 5))
def test_is_solved(self):
sudoku = Sudoku(grid)
self.assertFalse(sudoku.is_solved())
sudoku.grid = grid_solved
self.assertTrue(sudoku.is_solved())
def test_solve(self):
sudoku = Sudoku(grid)
sudoku.solve()
self.assertEqual(sudoku.grid.__repr__(), grid_solved.__repr__())
if __name__ == '__main__':
main()

View File

@ -0,0 +1,11 @@
from Sudoku import Sudoku
from example import grid
sudoku = Sudoku(grid)
print(f'\nSudoku | is_solved = {sudoku.is_solved()}\n')
print(sudoku)
print('-------------------------------------\n')
sudoku.solve()
print(f'Sudoku | is_solved = {sudoku.is_solved()}\n')
print(sudoku)

View File

@ -0,0 +1,21 @@
from Grid import Grid
grid = Grid([[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]])
grid_solved = 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]])

View File

@ -0,0 +1,23 @@
from typing import List
import sys
from Sudoku import Sudoku
from Grid import Grid
grid_values: List[List[int]] = []
for value in sys.stdin:
row_values = value.rstrip('\n').split(' ')
current_row: List[int] = []
for row_value in row_values:
current_row.append(int(row_value))
grid_values.append(current_row)
grid = Grid(grid_values)
sudoku = Sudoku(grid)
sudoku.solve()
for row in sudoku.grid.data:
column_string = ''
for column in row:
column_string += str(column) + ' '
print(column_string.strip())