From c21972037849e8b6821c996af978a8b2743b68fb Mon Sep 17 00:00:00 2001 From: aHardReset Date: Wed, 23 Dec 2020 14:24:58 -0800 Subject: [PATCH] Initial commit, solver ready, generator ready --- .gitignore | 5 +++ Sudoku.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ __init__.py | 0 main.py | 13 +++++++ 4 files changed, 126 insertions(+) create mode 100644 .gitignore create mode 100644 Sudoku.py create mode 100644 __init__.py create mode 100644 main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e8ac45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +**/.venv/** +**/__pycache__/** +main.spec +dist/** +build/** \ No newline at end of file diff --git a/Sudoku.py b/Sudoku.py new file mode 100644 index 0000000..0090229 --- /dev/null +++ b/Sudoku.py @@ -0,0 +1,108 @@ +class Sudoku: + def __init__(self, board:list = []) -> None: + if board == []: + self.board = self.generate_board() + else: + self.board = board + + @staticmethod + def generate_board(): + base = 3 + side = base*base + + # pattern for a baseline valid solution + def pattern(r,c): return (base*(r%base)+r//base+c)%side + + # randomize rows, columns and numbers (of valid base pattern) + from random import sample + def shuffle(s): return sample(s,len(s)) + rBase = range(base) + rows = [ g*base + r for g in shuffle(rBase) for r in shuffle(rBase) ] + cols = [ g*base + c for g in shuffle(rBase) for c in shuffle(rBase) ] + nums = shuffle(range(1,base*base+1)) + + # produce board using randomized baseline pattern + board = [ [nums[pattern(r,c)] for c in cols] for r in rows ] + + squares = side*side + empties = squares * 3//4 + for p in sample(range(squares),empties): + board[p//side][p%side] = 0 + return board + + def is_valid(self, num:int, pos:tuple) -> bool: + for i in range(len(self.board[0])): + if self.board[pos[0]][i] == num and pos[1] != i: + return False + + for i in range(len(self.board)): + if self.board[i][pos[1]] == num and pos[0] != i: + return False + + box_x = pos[1] // 3 + box_y = pos[0] // 3 + + for i in range(box_y*3, box_y*3 + 3): + for j in range(box_x*3, box_x*3 +3): + if self.board[i][j] == num and (i,j) != pos: + return False + return True + + def find_empty(self)-> tuple: + for i in range(len(self.board)): + for j in range(len(self.board[0])): + if self.board[i][j] == 0: + return(i,j) + return (-1, -1) + + def solve(self) -> bool: + find = self.find_empty() + if find == (-1, -1): + return True + row, col = find + + for i in range(1,10): + if self.is_valid(i, (row, col)): + self.board[row][col] = i + + if self.solve(): + return True + self.board[row][col] = 0 + return False + + + def __str__(self) -> str: + print_str = "" + for i in range(len(self.board)): + if i % 3 == 0 and i != 0: + print_str += "-----------------------\n" + + for j in range(len(self.board[0])): + if j % 3 == 0 and j != 0: + print_str += " | " + + print_str += str(self.board[i][j]) + print_str += "\n" if j == len(self.board[0]) -1 else " " + + + return print_str + + + #return super().__str__() + + + + +""" +board = [ + [7,8,0,4,0,0,1,2,0], + [6,0,0,0,7,5,0,0,9], + [0,0,0,6,0,1,0,7,8], + [0,0,7,0,4,0,2,6,0], + [0,0,1,0,5,0,9,3,0], + [9,0,4,0,6,0,0,0,5], + [0,7,0,3,0,0,0,1,2], + [1,2,0,0,0,7,4,0,0], + [0,4,9,2,0,6,0,0,7] + ] +""" \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py new file mode 100644 index 0000000..4a409d6 --- /dev/null +++ b/main.py @@ -0,0 +1,13 @@ +from Sudoku import Sudoku + +print("\nWelcome...\n\nGenerating new sudoku board\n") +a = Sudoku() +print(a) +input("Press enter to view solution\n") +solved = a.solve() + +print(a) if solved else print("Not solvable") + +print("\nThe Backtracking Algorithm is used to generate the solution") + +input("\nThanks for play... Press enter to exit") \ No newline at end of file