def __init__(self, screen, autostart=True, save_file=None): self.screen = screen screen.timeout(50) curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) self.save_file = save_file if save_file else os.path.join( os.path.expanduser("~"), ".sudoku") self.board = Board(3) self.current_board = Board(self.board) self.default_message = "WELCOME {}!".format(getpass.getuser()).upper() self.message_time = None self._row = 0 self._col = 0 self.max_row = self.board.rows + self.board.rows // self.board.unit self.max_col = 2 * (self.board.cols + self.board.cols // self.board.unit) self.board_win = CursesFrame( self.screen.subwin(self.max_row + 2, self.max_col + 2, 0, 0)) self.message_win = CursesFrame( self.screen.subwin(1, curses.COLS - 1, self.board_win.pary + self.board_win.maxy, 0)) self.help_win = CursesFrame( self.screen.subwin( 1, curses.COLS - 1, self.message_win.pary + self.message_win.maxy + 1, 0)) self.board_win.refresh() self.message(self.default_message) self.load() self.initialize() self._run = autostart if self._run: self.mainloop()
def main(): input_file = 'p096_sudoku.txt' output_file = 'output_files.txt' input_fhand = open(input_file, 'r') output_fhand = open(output_file, 'w') lines = input_fhand.readlines() lines = [line.strip('\n') for line in lines if line[:4]!= 'Grid'] ind = 0 grid_num = 1 project_euler_output = 0 while True: if ind >= len(lines): break sudoku_puzzle = lines[ind: ind + 9] #print(sudoku_puzzle[1][1], end = ' ') board = Board() for c in range(9): for r in range(9): board.board[c][r].number = int(sudoku_puzzle[c][r]) board.solve() output_fhand.write("Grid " + "{:02d}".format(grid_num) + "\n") output_fhand.write(str(board)) proj_euler_list = [board.board[0][0].number, board.board[0][1].number,\ board.board[0][2].number] project_euler_output += int(''.join(str(e) for e in proj_euler_list)) grid_num += 1 ind += 9 print(project_euler_output)
def new_board(self): self.message("Generating New Board...") self.board = cull_board(generate_board(), 0.6) self.current_board = Board(self.board) self.save() self.refresh() self.message("New Board Generated!")
def load(self): if not os.path.isfile(self.save_file): self.new_board() else: try: with open(self.save_file) as save_file: lines = [[cell.strip() for cell in line.split(',')] for line in save_file.readlines()] # [print(line) for line in lines] # time.sleep(60) dimension = len(lines[0]) self.board = Board(int(math.sqrt(dimension))) self.current_board = Board(int(math.sqrt(dimension))) for row in range(dimension): for col in range(dimension): # Get the root board item item = lines[row][col] if item != "": self.board[(row, col)] = int(item) # Get the current board item item = lines[row + dimension][col] if item != "": self.current_board[(row, col)] = int(item) except IndexError: self.new_board()
def main(argv): # Parsing aruments args = parse_arguments(argv) # cpu time calculations times = [] cpu_time = [] # number of calculations n_list=[] # defining step-size n=10 # if using "--rn" command - Repeatitively n if(args.rn !=0): # iterate each an increasing n=10 while it's smaller than the defined n in cmd/bash while n <= args.rn: # read benchmark file and get the arguments for i, board in enumerate(read_benchmark_file(args.benchmark), start=1): # append the cpu time for each solution finding for a board times.append(timeit.timeit(lambda: find_one_solution(Board(board), verbose=False), number=1)) # continue for the next puzzle by break if i == args.n: break # apeending cpu time for each iteration cpu_time.append(sum(times)) # appending n number of calculation n_list.append(n) # printing summary information print(f"Runs: {n}, Total time (sec): {sum(times):.3f}, Max: {max(times):.3f}," f" Min: {min(times):.3f}, Avg: {statistics.mean(times):.3f}, stdev: {statistics.stdev(times):.3f}") n=n+10 # plot cpu time as a function of n plt.plot(n_list,cpu_time) plt.title("CPU TIME") # save plot plt.savefig("CPU_TIME"+str(len)+".png") # initialize cpu times times=[] # if using "--n" command - NOT! Repeatitively n else: for i, board in enumerate(read_benchmark_file(args.benchmark), start=1): # appending cpu time times.append(timeit.timeit(lambda: find_one_solution(Board(board), verbose=False), number=1)) # continue for the next puzzle by break if i == args.n: break # printing summary information print(f"Runs: {args.n}, Total time (sec): {sum(times):.3f}, Max: {max(times):.3f}," f" Min: {min(times):.3f}, Avg: {statistics.mean(times):.3f}, stdev: {statistics.stdev(times):.3f}") times = [] cpu_time = [] cpu_time_all = [] n_list=[] n=10 """
def test_set_cell_value_clears_option_from_row_cells(): board = Board() board.set((1, 6), 5) for i in range(0, 9): cell = board[1][i] if i != 6: assert 5 not in cell.options else: assert cell.value == 5 assert cell.options == set()
def test_numbers_in_box_valid(): input_array = [ [0, 0, 0, 0, 9, 0, 0, 5, 2], [0, 1, 0, 0, 0, 0, 3, 0, 4], [0, 0, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) assert_equals(b._numbers_in_box(3, 3), set((7, 4, 6, 9, 1, 2, 5, 3)))
def test_numbers_in_col_valid(): input_array = [ [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 3, 0, 4], [0, 0, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) assert_equals(b._numbers_in_column(8), set((4, 9)))
def test_board_iter_rows(): board = Board(EMPTY_BOARD_ARR) expected = [ np.array([8, 0, 1, 0, 0, 3, 9, 0, 6]), np.array([0, 0, 9, 0, 0, 7, 8, 5, 0]), np.array([2, 5, 0, 1, 0, 0, 4, 7, 0]), np.array([5, 0, 0, 0, 6, 1, 7, 0, 4]), np.array([7, 6, 0, 8, 3, 0, 0, 0, 0]), np.array([0, 3, 2, 0, 0, 0, 0, 0, 0]), np.array([0, 2, 0, 0, 1, 9, 5, 0, 0]), np.array([0, 0, 5, 0, 0, 0, 3, 0, 2]), np.array([0, 0, 0, 4, 5, 2, 1, 9, 7]) ] assert np.array_equal(board.iter_rows(), expected)
def test_is_valid_start_board_valid(): input_array = [ [0, 0, 0, 0, 9, 0, 0, 5, 2], [0, 1, 0, 0, 0, 0, 3, 0, 4], [0, 0, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) assert b._is_valid_start_board()
def test_numbers_in_row_empty(): input_array = [ # Clear out non-zeroes in first row [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 3, 0, 4], [0, 0, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) assert_equals(b._numbers_in_row(0), set())
def test_board_iter_blocks(): expected = [ np.array([[8, 0, 1], [0, 0, 9], [2, 5, 0]]), np.array([[0, 0, 3], [0, 0, 7], [1, 0, 0]]), np.array([[9, 0, 6], [8, 5, 0], [4, 7, 0]]), np.array([[5, 0, 0], [7, 6, 0], [0, 3, 2]]), np.array([[0, 6, 1], [8, 3, 0], [0, 0, 0]]), np.array([[7, 0, 4], [0, 0, 0], [0, 0, 0]]), np.array([[0, 2, 0], [0, 0, 5], [0, 0, 0]]), np.array([[0, 1, 9], [0, 0, 0], [4, 5, 2]]), np.array([[5, 0, 0], [3, 0, 2], [1, 9, 7]]), ] board = Board(EMPTY_BOARD_ARR) assert np.array_equal(board.iter_blocks(), expected)
def test_make_moves_failed_board(): input_array = [ # Second number on first row has no moves left [3, 0, 7, 6, 9, 4, 1, 5, 2], [5, 1, 9, 0, 7, 0, 3, 8, 4], [8, 6, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) assert_equals(b.make_moves(), None)
def test_valid_moves_9(): input_array = [ [3, 4, 6, 0, 9, 0, 0, 5, 2], [0, 1, 5, 0, 0, 0, 3, 0, 4], [7, 8, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) result = b.valid_moves(1, 0) assert_equals(result, [9])
def test_board_iter_cols(): expected = [ np.array([8, 0, 2, 5, 7, 0, 0, 0, 0]), np.array([0, 0, 5, 0, 6, 3, 2, 0, 0]), np.array([1, 9, 0, 0, 0, 2, 0, 5, 0]), np.array([0, 0, 1, 0, 8, 0, 0, 0, 4]), np.array([0, 0, 0, 6, 3, 0, 1, 0, 5]), np.array([3, 7, 0, 1, 0, 0, 9, 0, 2]), np.array([9, 8, 4, 7, 0, 0, 5, 3, 1]), np.array([0, 5, 7, 0, 0, 0, 0, 0, 9]), np.array([6, 0, 0, 4, 0, 0, 0, 2, 7]) ] board = Board(EMPTY_BOARD_ARR) assert np.array_equal(board.iter_columns(), expected)
def test_valid_moves_none_left(): input_array = [ # Second number on first row has no moves left [3, 0, 7, 6, 9, 4, 1, 5, 2], [5, 1, 9, 0, 7, 0, 3, 8, 4], [8, 6, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) assert_equals(b.valid_moves(0, 1), [])
def render_sudoku(request): unit = 3 page_html = '<table style="border-collapse: collapse; padding: 0;">' try: values = [] for x in request.GET["values"].split(","): values.append(int(x) if x else None) except (ValueError, KeyError): return new_board(request) if len(values) != unit ** 4: return new_board(request) board = Board(unit) for i, value in enumerate(values): if value is not None: board[(i // 9, i % 9)] = value for row in range(board.rows): page_html += '<tr style="padding: 0;">' for col in range(board.cols): page_html += '<td width=25 height=25 style="text-align: center; padding: 0; border: 1px solid gray;">{}</td>'.format(board[(row, col)] if (row, col) in board else '') page_html += "</tr>" page_html += "</table>" response = request.response response.body = bytes(page_html, request.url_encoding) response.headers["Access-Control-Allow-Origin"] = "*" return response
def remove_cell(board: Board, solutions: Solutions, cells_to_remove: int = 0) -> list: """ Given a board with a unique solution and a dictionary of board-hash -> solution-board-hash, remove a random cell from the board and test if the resulting board also has a unique solution (every legal move also results boards that have unique solutions). Also adds the new board to unique_solutions If no board with a unique solution can be created, returns None :param board: :param solutions: :param cells_to_remove: :return: """ assert board in solutions assert cells_to_remove >= 0 new_puzzles = [] xs, ys = np.nonzero(board.board) indices = np.arange(len(xs)) np.random.shuffle(indices) for i in indices: x, y = xs[i], ys[i] new_board = board.remove(x, y) # remove is a relatively expensive step (Still O(1)). Can short circuited for checking if the board # already exists in solutions, but b/c of the way hashing works, not quite so simple to # implement. Might be worth doing in the future. if (new_board in solutions and solutions[new_board]) or len( solutions.find_all_solutions(new_board)) == 1: new_puzzles.append(new_board) if cells_to_remove and len(new_puzzles) >= cells_to_remove: return new_puzzles return new_puzzles if new_puzzles else None
def test_numbers_in_row_valid(): input_array = [ [0, 0, 0, 0, 9, 0, 0, 5, 2], [0, 1, 0, 0, 0, 0, 3, 0, 4], [0, 0, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) result = b._numbers_in_row(0) # Two sets are equal iff every element of each set is contained in the other assert_equals(result, set((2, 5, 9)))
def test_valid_moves_valid(): input_array = [ [0, 0, 0, 0, 9, 0, 0, 5, 2], [0, 1, 0, 0, 0, 0, 3, 0, 4], [0, 0, 2, 3, 1, 5, 0, 0, 9], [0, 0, 8, 7, 4, 6, 0, 3, 0], [0, 7, 0, 9, 0, 1, 0, 2, 0], [0, 9, 0, 2, 5, 3, 7, 0, 0], [4, 0, 0, 5, 3, 8, 2, 0, 0], [2, 0, 3, 0, 0, 0, 0, 6, 0], [1, 5, 0, 0, 6, 0, 0, 0, 0] ] b = Board(input_array) result = b.valid_moves(0, 0) assert_equals(type(result), list) assert_equals(set(result), set((3, 6, 7, 8)))
def test_board_has_81_cells(): board = Board() assert board[0][0].options == set(range(1, 10)) assert board[8][8].options == set(range(1, 10)) with pytest.raises(KeyError): assert board[0][9] with pytest.raises(KeyError): assert board[9][0]
def detect_invalid_solutions(filename): from sudoku import Board, is_valid puzzles = read_sudokus_from_csv(filename, read_solutions=True) list_invalids = [] for puzzle in puzzles: puzzle_obj = Board(puzzle) if not is_valid(puzzle_obj): list_invalids.append(puzzle) return np.array(list_invalids)
def test_board_creation_string(): expected = np.array([[8, 0, 1, 0, 0, 3, 9, 0, 6], [0, 0, 9, 0, 0, 7, 8, 5, 0], [2, 5, 0, 1, 0, 0, 4, 7, 0], [5, 0, 0, 0, 6, 1, 7, 0, 4], [7, 6, 0, 8, 3, 0, 0, 0, 0], [0, 3, 2, 0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 1, 9, 5, 0, 0], [0, 0, 5, 0, 0, 0, 3, 0, 2], [0, 0, 0, 4, 5, 2, 1, 9, 7]]) board = Board(EMPTY_BOARD_STR) assert np.array_equal(board.arr, expected)
def main(argv): args = parse_arguments(argv) times = [] for i, board in enumerate(read_benchmark_file(args.benchmark), start=1): times.append( timeit.timeit( lambda: find_one_solution(Board(board), verbose=False), number=1)) if i == args.n: break print( f"Runs: {args.n}, Total time (sec): {sum(times):.3f}, Max: {max(times):.3f}," f" Min: {min(times):.3f}, Avg: {statistics.mean(times):.3f}, stdev: {statistics.stdev(times):.3f}" )
def test_find_empty(): expected = np.array([[0, 1], [0, 3], [0, 4], [0, 7], [1, 0], [1, 1], [1, 3], [1, 4], [1, 8], [2, 2], [2, 4], [2, 5], [2, 8], [3, 1], [3, 2], [3, 3], [3, 7], [4, 2], [4, 5], [4, 6], [4, 7], [4, 8], [5, 0], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [6, 0], [6, 2], [6, 3], [6, 7], [6, 8], [7, 0], [7, 1], [7, 3], [7, 4], [7, 5], [7, 7], [8, 0], [8, 1], [8, 2]]) board = Board(EMPTY_BOARD_ARR) assert np.array_equal(find_empty(board), expected)
def generate_puzzle(self, difficulty): # Generates a random completed sudoku puzzle puzzle = Board([0 for i in range(81)]) puzzle.solve_board() self.completed = puzzle hint_num = 30 + (4 - difficulty) * 8 # Randomly select positions to be clues ls = list(range(81)) # Try until set of clues given produce a unique solution while True: random.shuffle(ls) clues = ls[:hint_num] starting = [0 for i in range(81)] for i in clues: starting[i] = self.completed.get_data()[i] possible = Board(starting) if (possible.check_unique()): self.given = possible break
def test_is_invalid(): board = Board(INVALID_BOARD_ARR) assert is_valid(board) is False
"--puzzles", help="The number of new minimum hint puzzles to create.", type=int) parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") args = parser.parse_args() assert args.solution_file or (args.dim_x and args.dim_y) solution_file = args.solution_file verbose = args.verbose if solution_file: solutions = Solutions(solution_file) else: solution_file = '../../data/solutions_{0}.txt'.format( utils.datetime_to_str(datetime.utcnow())) solutions = Solutions(solution_file) board = Board(args.dim_x, args.dim_y) for i in range(args.dim_x * args.dim_y): board.write(0, i, i + 1) print("Finding solutions") solutions.find_all_solutions(board) print("Beginning sequence") for i in tqdm(range(args.puzzles)): sol = solutions.get_min_puzzle_seed_solution() generate_new_puzzle(sol, solutions) solutions.save()
def test_subset_valid_block(): board = Board(VALID_BOARD_ARR) assert is_subset_valid(board.get_block(0, 1)) is True
def test_is_valid(): board = Board(VALID_BOARD_ARR) assert is_valid(board) is True
def test_subset_valid_row(): board = Board(VALID_BOARD_ARR) assert is_subset_valid(board.get_row(0)) is True
def test_subset_valid_column(): board = Board(VALID_BOARD_ARR) assert is_subset_valid(board.get_column(4)) is True
def test_subset_invalid_row(): board = Board(INVALID_BOARD_ARR) assert is_subset_valid(board.get_row(0)) is False
def test_subset_invalid_column(): board = Board(INVALID_BOARD_ARR) assert is_subset_valid(board.get_column(4)) is False
def test_is_full(): assert is_full(Board(EMPTY_BOARD_ARR)) is False, is_full( Board(EMPTY_BOARD_ARR)) assert is_full(Board(SOLVED_BOARD_ARR)) is True
def test_find_possibilities(): board = Board(EMPTY_BOARD_ARR) assert set(find_possibilities(board, 0, 1)) == set([4, 7]) assert set(find_possibilities(board, 1, 0)) == set([3, 4, 6]) assert set(find_possibilities(board, 1, 1)) == set([4])
def test_board_get_blocks(): board = Board(EMPTY_BOARD_ARR) assert np.array_equal(board.get_block(1, 2), np.array([[7, 0, 4], [0, 0, 0], [0, 0, 0]]))
def test_board_get_cols(): board = Board(EMPTY_BOARD_ARR) assert np.array_equal(board.get_column(4), np.array([0, 0, 0, 6, 3, 0, 1, 0, 5]))
def test_board_get_rows(): board = Board(EMPTY_BOARD_ARR) assert np.array_equal(board.get_row(2), np.array([2, 5, 0, 1, 0, 0, 4, 7, 0])) assert np.array_equal(board.get_row(8), np.array([0, 0, 0, 4, 5, 2, 1, 9, 7]))