def __init__(self): super().__init__() self.setWindowTitle("Sudoku Solver") self.widget_cells = [] self.window = QWidget(self) self._set_to_initial_layout() self.solver = SudokuSolver()
class SudokuController: """ Controller layer from logic to UI to file handler""" def __init__(self): print('init controller') self.solver = SudokuSolver(self) self.gui = SudokuUI(self) self.filehandler = SudokuFilehandler(self) self.gui.call_mainloop() # updates the sudoku grid on the UI def update_gui_grid(self, grid): self.gui.update_gui_grid(grid) # starts the search for a solution for the given grid def search_solution(self, grid): self.solver.main(grid) # shows a message on the UI def show_message_on_gui(self, title, message): self.gui.show_message(title, message) # opens a file and shows the grid it on the UI def handle_file(self, filename): try: grid = self.filehandler.convert_file_to_grid(filename) self.gui.update_gui_grid(grid) except (ValueError, IllegalFormatException) as e: self.gui.show_message('Error', 'Wrong format of input file')
def test_solver(): board = [ ["9", "", "", "", "", "8", "", "7", ""], ["5", "", "", "6", "7", "9", "2", "3", ""], ["1", "", "", "", "", "5", "9", "6", ""], ["8", "5", "", "7", "", "2", "6", "", ""], ["", "", "9", "8", "", "", "7", "", "2"], ["3", "7", "", "1", "", "", "", "", ""], ["", "", "4", "", "3", "", "5", "8", "6"], ["", "8", "3", "", "6", "", "", "", "4"], ["", "1", "5", "", "8", "", "", "", ""], ] solution = [ ["9", "2", "6", "3", "1", "8", "4", "7", "5"], ["5", "4", "8", "6", "7", "9", "2", "3", "1"], ["1", "3", "7", "4", "2", "5", "9", "6", "8"], ["8", "5", "1", "7", "9", "2", "6", "4", "3"], ["4", "6", "9", "8", "5", "3", "7", "1", "2"], ["3", "7", "2", "1", "4", "6", "8", "5", "9"], ["7", "9", "4", "2", "3", "1", "5", "8", "6"], ["2", "8", "3", "5", "6", "7", "1", "9", "4"], ["6", "1", "5", "9", "8", "4", "3", "2", "7"], ] sudoku = SudokuSolver(board=board) solutions = [_ for _ in sudoku.solve_all()] assert len(solutions) == 1 assert solutions[0].board == solution assert sudoku.solve().board == solution
def test_multiple_solutions(): board = [ ["", "4", "", "1"], ["1", "", "4", ""], ["", "1", "", "4"], ["4", "", "1", ""], ] solutions = [ [ ["3", "4", "2", "1"], ["1", "2", "4", "3"], ["2", "1", "3", "4"], ["4", "3", "1", "2"], ], [ ["2", "4", "3", "1"], ["1", "3", "4", "2"], ["3", "1", "2", "4"], ["4", "2", "1", "3"], ], ] sudoku = SudokuSolver(board=board) sudoku_solutions = [_ for _ in sudoku.solve_all()] assert len(solutions) == 2 assert [s.board for s in sudoku_solutions] == solutions assert sudoku.solve().board == solutions[0]
def test_all_positions_and_numbers_are_possible_on_zero_grid(self): grid = create_zero_grid() solver = SudokuSolver(grid) for number in range(1, 10): for col in range(9): for row in range(9): self.assertTrue(solver._is_possible(col,row,number))
def test_find_safest_position_to_solve(self): grid = create_solved_grid() solution = grid[8][8] grid[8][8] = 0 solver = SudokuSolver(grid) self.assertEqual( solver.find_safest_position_to_solve(), ( (8, 8),[solution]) )
def test_solve_missing_one_number(self): grid = create_solved_grid() grid[0][0] = 0 solver = SudokuSolver(grid) self.assertTrue( solver.brut_force() ) self.assertEqual(solver._grid , create_solved_grid() )
def __init__(self): pygame.init() self.sudoku_rules = SudokuSolver() self.size = FULLSIZE self.screen = pygame.display.set_mode(self.size) pygame.display.set_caption("SUDOKU") self.screen.fill(WHITE) self.draw_grid()
class SudokuArSolver: MAX_IMG_SIZE = 400 def __init__(self): self.grid_detector = GridDetector() self.warper = ImageWarper() self.sudoku_solver = SudokuSolver(9) self.digit_reader = DigitReader() def solve(self, image): image = self.scale_too_big_image(image) grid_corners = self.grid_detector.find_grid(image, show_img=True) if grid_corners is None: return image warp = self.warper.warp(self.grid_detector.thresh_image, grid_corners) table = self.digit_reader.read_numbers(warp) self.sudoku_solver.print_grid(table) solved_table = self.sudoku_solver.solve(copy.deepcopy(table)) image_with_numbers = self.warper.write_number_to_image( warp, table, solved_table) res = self.warper.draw_warp_to_original(image_with_numbers, image) return res @staticmethod def scale_too_big_image(image): mx_size = np.max(image.shape) if mx_size > SudokuArSolver.MAX_IMG_SIZE: scale = mx_size / SudokuArSolver.MAX_IMG_SIZE return cv2.resize( image, (int(image.shape[1] / scale), int(image.shape[0] / scale))) return image def load_pic(self, path): image = cv2.imread(path) res = self.solve(image) cv2.imshow('frame', res) cv2.waitKey() def start_camera(self): cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() # frame = frame[60:-60, 60:-60] frame = frame[60:60 + 360, 180:180 + 360] res = self.solve(frame) cv2.imshow('Video', res) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
def test_cannot_insert_number_if_it_is_already_on_same_column(self): grid = create_zero_grid() col = 3 number = 8 grid[col][2] = number solver = SudokuSolver(grid) self.assertFalse(solver._is_possible(col,4,number)) # ok for neighbor col self.assertTrue(solver._is_possible(col + 1, 4 ,number))
def test_cannot_insert_number_if_it_is_already_on_same_row(self): grid = create_zero_grid() row = 3 number = 8 grid[2][row] = number solver = SudokuSolver(grid) self.assertFalse(solver._is_possible(4,row,number)) # ok for neighbor row self.assertTrue(solver._is_possible(4,row + 1,number))
def _erase(self, board: Board) -> Board: while True: i, j = self._get_next_coords() board_c = deepcopy(board) board_c[i][j] = "" sudoku = SudokuSolver(board=board_c) if len([_ for _ in sudoku.solve_all()]) > 1: return board board = board_c
def test_incorrect_board(): board = [ ["1", "1", "1", "1"], ["", "", "", "4"], ["4", "", "3", "1"], ["3", "2", "4", ""], ] sudoku = SudokuSolver(board=board) solution = [_ for _ in sudoku.solve_all()] assert len(solution) == 0 assert sudoku.solve() is None
def test_cannot_insert_number_if_it_is_already_on_same_block(self): grid = create_zero_grid() number = 8 grid[1][1] = number grid[4][4] = number grid[7][7] = number solver = SudokuSolver(grid) self.assertFalse(solver._is_possible(2,2,number)) self.assertFalse(solver._is_possible(5,5,number)) self.assertFalse(solver._is_possible(8,8,number))
def main(): board = SudokuBoard() board.add_element(0, 3, 3) board.add_element(0, 4, 4) board.add_element(0, 5, 6) board.add_element(0, 7, 5) board.add_element(0, 8, 9) ########### # board.add_element(0, 0, 5) # board.add_element(0, 1, 3) # board.add_element(0, 4, 7) # board.add_element(1, 0, 6) # board.add_element(1, 3, 1) # board.add_element(1, 4, 9) # board.add_element(1, 5, 5) # board.add_element(2, 1, 9) # board.add_element(2, 2, 8) # board.add_element(2, 7, 6) # board.add_element(3, 0, 8) # board.add_element(3, 4, 6) # board.add_element(3, 8, 3) # board.add_element(4, 0, 4) # board.add_element(4, 3, 8) # board.add_element(4, 5, 3) # board.add_element(4, 8, 1) # board.add_element(5, 0, 7) # board.add_element(5, 4, 2) # board.add_element(5, 8, 6) # board.add_element(6, 1, 6) # board.add_element(6, 6, 2) # board.add_element(6, 7, 8) # board.add_element(7, 3, 4) # board.add_element(7, 4, 1) # board.add_element(7, 5, 9) # board.add_element(7, 8, 5) # board.add_element(8, 4, 8) # board.add_element(8, 7, 7) # board.add_element(8, 8, 9) # board.build_board() solver = SudokuSolver(board) if solver.board.is_valid_full(): print("Board before solving: \n") print(board, "\n") if solver.backtracking(0, 0): print("Sudoku has been solved \n") print(board) if solver.board.is_valid_full(): print("Solution Exists!!") else: print("Board entered is not valid. Please enter a valid board.")
def solve_puzzle(): cells = [[0 for _ in range(9)] for _ in range(9)] for i in range(9): for j in range(9): if request.args[str(i) + str(j)]: cells[i][j] = int(request.args[str(i) + str(j)]) solver = SudokuSolver(cells) result, grid, path = solver.solve() return render_template('index.html', solution=True, result=result, content=path)
def setUp(self): self.board = [[0, 0, 0, 2, 6, 0, 7, 0, 1], [6, 8, 0, 0, 7, 0, 0, 9, 0], [1, 9, 0, 0, 0, 4, 5, 0, 0], [8, 2, 0, 1, 0, 0, 0, 4, 0], [3, 0, 4, 6, 0, 2, 9, 0, 0], [0, 5, 0, 0, 0, 3, 0, 2, 8], [0, 0, 9, 3, 0, 0, 0, 7, 4], [0, 4, 0, 0, 5, 0, 0, 3, 6], [7, 0, 3, 0, 1, 8, 0, 0, 0]] self.solver = SudokuSolver(self.board) self.solver.solve() self.result = [i for i in range(1, 10)]
def test_simple_solver(): board = [ ["1", "", "2", "3"], ["2", "", "1", "4"], ["4", "", "3", "1"], ["3", "", "4", ""], ] solution = [list("1423"), list("2314"), list("4231"), list("3142")] sudoku = SudokuSolver(board=board) solutions = [_ for _ in sudoku.solve_all()] assert len(solutions) == 1 assert solutions[0].board == solution assert sudoku.solve().board == solution
def fill_solve(self, grid): global counter for i in range(0, 81): row = i // 9 column = i % 9 if grid[row][column] == 0: for value in range(1, 10): #Check that this value has not already be used on this row if not (value in grid[row]): #Check that this value has not already be used on this column if not value in (grid[0][column], grid[1][column], grid[2][column], grid[3][column], grid[4][column], grid[5][column], grid[6][column], grid[7][column], grid[8][column]): #Identify which of the 9 squares we are working on square = get_square_3x3(grid, row, column) if not value in (square[0] + square[1] + square[2]): grid[row][column] = value if SudokuSolver.check_grid(grid): counter += 1 break else: if self.fill_solve(grid): return True break grid[row][column] = 0
def test_non_unique_solver(): # just test that this completes for a non unique board board = [ ["1", "", "", "", "", "", "", "", ""], ["", "2", "", "", "", "", "", "", ""], ["", "", "3", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ] sudoku = SudokuSolver(board=board) solution = sudoku.solve() assert all(r != "" for row in solution.board for r in row)
def generate_sudoku(): sudoku_solver = SudokuSolver() array = [[0 for i in range(9)] for j in range(9)] rand_entry = randint(1, 9) rand_row, rand_col = (randint(0, 8), randint(0, 8)) array[rand_row][rand_col] = rand_entry sudoku_solver.solve(array) values_to_remove = sample([(j, k) for j in range(0, 9) for k in range(0, 9)], 48) for el in values_to_remove: array[el[0]][el[1]] = 0 solvable_array = deepcopy(array) if not sudoku_solver.solve(solvable_array): break return array
def solve_puzzle(puzzle_strings): puzzle_id = puzzle_strings[0] solve_set = set() puzzle = Puzzle(puzzle_strings[1][0], solve_set) solution = Puzzle(puzzle_strings[1][1]) solver = SudokuSolver(puzzle, solve_set) solver.solve() if solver.puzzle == solution: print("Puzzle", puzzle_id, "Complete!") return 1 else: print("Bad Solution for", puzzle_id) return 0
def main(): initial_board_values = [ [0, 9, 6, 0, 4, 0, 0, 3, 0], [0, 5, 7, 8, 2, 0, 0, 0, 0], [1, 0, 0, 9, 0, 0, 5, 0, 0], [0, 0, 9, 0, 1, 0, 0, 0, 8], [5, 0, 0, 0, 0, 0, 0, 0, 2], [4, 0, 0, 0, 9, 0, 6, 0, 0], [0, 0, 4, 0, 0, 3, 0, 0, 1], [0, 0, 0, 0, 7, 9, 2, 6, 0], [0, 2, 0, 0, 5, 0, 9, 8, 0], ] board = Board(initial_board_values) sudoku_solver = SudokuSolver() sudoku_solver.prepare(board) start_time = time.time() sudoku_solver.run() elapsed_time = time.time() - start_time result = sudoku_solver.get_result() print('Puzzle solved?: {}'.format(result.success)) print('Elapsed time (s): {}'.format(elapsed_time)) if result.success: print('\nInitial board:\n') print(board) board.update_units_by_name(result.assignment.state) print('\nSolved board:\n') print(board)
def __init__(self, tile, digit, sudoku_board, children=None): self.solver = SudokuSolver() self.solver.sudoku_board = copy.deepcopy(sudoku_board) self.tile = tile self.digit = digit self.children = [] if children is not None: for child in children: self.add_child(child)
def main(): sudoku = SudokuSolver() sudoku.check_valid_solutions(sudoku.sudoku_board) sudoku.write_definite_solutions_loop() sudoku.tree_preprocessing() ### SOLVING SUDOKU USING TREE tree = SudokuTree((-1, -1), 0, sudoku.sudoku_board) recursion(sudoku, tree) print "bla"
class TestSudoku(unittest.TestCase): def setUp(self): self.board = [[0, 0, 0, 2, 6, 0, 7, 0, 1], [6, 8, 0, 0, 7, 0, 0, 9, 0], [1, 9, 0, 0, 0, 4, 5, 0, 0], [8, 2, 0, 1, 0, 0, 0, 4, 0], [3, 0, 4, 6, 0, 2, 9, 0, 0], [0, 5, 0, 0, 0, 3, 0, 2, 8], [0, 0, 9, 3, 0, 0, 0, 7, 4], [0, 4, 0, 0, 5, 0, 0, 3, 6], [7, 0, 3, 0, 1, 8, 0, 0, 0]] self.solver = SudokuSolver(self.board) self.solver.solve() self.result = [i for i in range(1, 10)] def test_row(self): """ Checks if every row contains value from 1 to 9 or not. Also checks if there are any duplicate items or not. """ for i in range(len(self.solver.board[0])): self.assertListEqual(sorted(self.solver.board[i]), self.result) def test_column(self): """ Checks if every column contains value from 1 to 9 or not. Also checks if there are any duplicate items or not. """ for i in range(len(self.solver.board[0])): res = [self.solver.board[j][i] for j in range(9)] self.assertListEqual(sorted(res), self.result) def test_box(self): """ Checks if every 3*3 box contains value from 1 to 9 or not. Also checks if there are any duplicate items or not. """ for row in range(3): for col in range(3): start_x = row * 3 start_y = col * 3 vals = [self.solver.board[row][col] for col in range( start_y, start_y+3) for row in range(start_x, start_x+3)] self.assertListEqual(sorted(vals), self.result)
def test_safest_first_solver_with_hard_one(self): print("test_safest_first_solver_with_hard_one") grid = create_hard_sudoku() solver = SudokuSolver(grid) self.assertTrue( solver.safest_first_solver() ) self.assertTrue( solver.check() ) solver._debug()
def test_safest_first_solver(self): print("test_safest_first_solver") grid = create_real_world_grid() solver = SudokuSolver(grid) self.assertTrue( solver.safest_first_solver() ) self.assertTrue( solver.check()) solver._debug()
def main(): # List of puzzles to solve puzzle_files = ["puzzle.txt", "puzzle2.txt", "puzzle3.txt", "puzzle4.txt"] print("Loading puzzles.") puzzles = [SudokuSolver.empty_puzzle()] for path in puzzle_files: try: puzzle = SudokuSolver.fromfile(path) except (NoSolutionFound, FileNotFoundError) as e: print(e) else: puzzles.append(puzzle) print("Puzzles loaded.\n") print("Starting to solve puzzles:") solver = SudokuSolver() for puzzle in puzzles: solver.puzzle = puzzle print("Trying to solve this sudoku puzzle:") print(solver.puzzle) try: solver.solve() except NoSolutionFound: print("There is no solution for this puzzle!") else: print("Solution found!") print(solver.solution)
def __init__(self, parent): self.ncells = 9 self.margin = 10 self.pixel_width = 500 self.canvas = Canvas(parent, width = self.pixel_width + 2 * self.margin, height = self.pixel_width + 2 * self.margin) self.canvas.bind("<Button-1>", self.change_cell) self.canvas.pack() self.button_solve = Button(parent, text = "Solve it!") self.button_solve.configure(command = self.solve) self.button_solve.pack() self.button_save = Button(parent, text = "Print") self.button_save.configure(command = self.save) self.button_save.pack() self.board = [[-1]*self.ncells for x in xrange(self.ncells)] self.solver = SudokuSolver()
def test_solve_real_word_sudoku(self): grid = create_real_world_grid() solver = SudokuSolver(grid) import time start = time.monotonic() self.assertTrue( solver.brut_force() ) end = time.monotonic() print ("elapsed = {} s".format(end - start)) self.assertTrue( solver.check()) solver._debug()
class SolverConstants: table = [ [0, 0, 0, 0, 0, 3, 0, 0, 6], [0, 0, 3, 5, 0, 0, 0, 8, 0], [1, 0, 0, 6, 4, 0, 0, 7, 3], [5, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 4, 8, 7, 0, 0, 0], [0, 8, 0, 0, 0, 0, 0, 0, 9], [4, 3, 0, 0, 2, 5, 0, 0, 7], [0, 5, 0, 0, 0, 6, 2, 0, 0], [7, 0, 0, 1, 0, 0, 0, 0, 0], ] easy_sudoku = [[0, 0, 0, 0, 5, 6, 0, 0, 2], [6, 0, 9, 7, 0, 2, 0, 0, 0], [0, 2, 7, 0, 0, 0, 0, 9, 0], [0, 6, 0, 0, 0, 9, 0, 0, 8], [5, 0, 0, 0, 0, 0, 3, 0, 4], [0, 1, 0, 0, 0, 7, 0, 0, 9], [0, 8, 6, 0, 0, 0, 0, 3, 0], [9, 0, 3, 2, 0, 1, 0, 0, 0], [0, 0, 0, 0, 9, 3, 0, 0, 6]] solver = SudokuSolver(table)
class SudokuGUI: def __init__(self, parent): self.ncells = 9 self.margin = 10 self.pixel_width = 500 self.canvas = Canvas(parent, width = self.pixel_width + 2 * self.margin, height = self.pixel_width + 2 * self.margin) self.canvas.bind("<Button-1>", self.change_cell) self.canvas.pack() self.button_solve = Button(parent, text = "Solve it!") self.button_solve.configure(command = self.solve) self.button_solve.pack() self.button_save = Button(parent, text = "Print") self.button_save.configure(command = self.save) self.button_save.pack() self.board = [[-1]*self.ncells for x in xrange(self.ncells)] self.solver = SudokuSolver() def save(self): out = 'sudoku.ps' tkMessageBox.showinfo("Print", "Printed solution to file %s"%out) self.canvas.postscript(file = 'sudoku.ps', colormode = 'color') def get_value(self, x): if x == -1: return ' ' return str(x) def solve(self): ok, ans = self.solver.solve(self.board) if not ok: tkMessageBox.showerror("FAIL", "Sudoku cannot be solved") return self.canvas.delete('all') for i in xrange(self.ncells): for j in xrange(self.ncells): if self.board[i][j] != ans[i][j]: self.draw_cell(i, j, self.get_value(ans[i][j]), color='blue') else: self.draw_cell(i, j, self.get_value(self.board[i][j]), color = 'black') print self.board def _get_next_value(self, snum): if snum == ' ': return '1' num = int(snum) num = (num + 1)%10 if num == 0: return ' ' else: return str(num) def update_text(self, e): value = self._get_next_value(self.canvas.itemcget(e, 'text')) self.canvas.itemconfigure(e, text = value) x, y = self.canvas.gettags(e)[1].split(' ') x, y = int(x), int(y) if value == ' ': self.board[x][y] = -1 else: self.board[x][y] = int(value) def change_cell(self, event): e = self.canvas.find_closest(event.x, event.y) if 'text' in self.canvas.gettags(e): self.update_text(e) else: if 'rectangle' in self.canvas.gettags(e): text_tag = self.canvas.gettags(e)[1] for x in self.canvas.find_withtag(text_tag): if 'text' in self.canvas.gettags(x): self.update_text(x) def draw_cell(self, i, j, value = ' ', color = 'black'): cellsize = self.pixel_width/self.ncells x1 = self.margin + i * cellsize y1 = self.margin + j * cellsize x2 = x1 + cellsize y2 = y1 + cellsize r_index = self.canvas.create_rectangle(x1, y1, x2, y2) t_index = self.canvas.create_text((x1 + x2)/2, (y1 + y2)/2, text=value, font = ('Helvectica', 30), fill = color) self.canvas.addtag_withtag('rectangle', r_index) self.canvas.addtag_withtag('%d %d'%(i, j), r_index) self.canvas.addtag_withtag('text', t_index) self.canvas.addtag_withtag('%d %d'%(i, j), t_index) if i % 3 == 0 and i > 0: self.canvas.create_line(x1, y1, x1, y1 + cellsize , width = 3) if j % 3 == 0 and j > 0: self.canvas.create_line(x1, y1, x1 + cellsize , y1, width = 3) def draw_board(self): for i in xrange(self.ncells): for j in xrange(self.ncells): if self.board[i][j] == -1: self.draw_cell(i, j) else: self.draw_cell(i, j, value = str(self.board[i][j]))
def testEvil(self): solver = SudokuSolver() solver.solve('../evilpuzzle.in') result = solver.printBoard() assert 'x' not in result, result +'\n' + solver.printTilePossibleValues() pass
def testHard(self): solver = SudokuSolver() solver.solve('../hardpuzzle.in') result = solver.printBoard() assert 'x' not in result, result pass
def solve(row_list): rows = [map(int, list(row)) for row in row_list] solver = SudokuSolver() result = solver.solve(rows) output(result)