Beispiel #1
0
def brute_force_solve_sudoku(sudoku: sudoku_board.Sudoku):
    # 'l' is a list variable that keeps the record of row and col in find_empty_location Function
    arr = sudoku.board_numbers

    location = [0, 0]

    # If there is no unassigned location, we are done
    if not find_empty_location(arr, location):
        return True

    # Assigning list values to row and col that we got from the above Function
    row = location[0]
    col = location[1]

    # consider digits 1 to 9
    for num in range(1, 10):

        # if looks promising
        if check_location_is_safe(arr, row, col, num):

            # make tentative assignment
            sudoku.add_cell(row, col, num)

            # return, if success, ya!
            if brute_force_solve_sudoku(sudoku):
                return True

            # failure, unmake & try again
            sudoku.add_cell(row, col, 0)

    # this triggers backtracking
    return False
def test_add_cell_with_valid():
    sudoku_board = Sudoku(boards.unsolved_easy)
    row = 3
    column = 7
    value = 5
    sudoku_board.add_cell(row, column, value)
    assert sudoku_board.board_numbers[row][column] == value
def test_solve_naked_subset_row():
    column = 1
    row = 0
    sudoku_board = Sudoku(boards.naked_pair_test)
    sudoku_board.board_numbers = sudoku_board.board_numbers.T
    assert sudoku_board.board_numbers[row, column] == 0
    sudoku_solver.solve_naked_subset_row(sudoku_board, row)
    assert sudoku_board.board_numbers[row, column] == 1
def test_add_cell_with_invalid():
    sudoku_board = Sudoku(boards.unsolved_easy)
    row = 3
    column = 7
    value = 's'
    with pytest.raises(Exception):
        # noinspection PyTypeChecker
        sudoku_board.add_cell(row, column, value)
def test_brute_force_solve_sudoku():
    board = Sudoku(boards.unsolved_easy)
    sudoku_solver.brute_force_solve_sudoku(board)
    assert (board.board_numbers == boards.solved_easy).all()

    board = Sudoku(boards.unsolved_hard)
    sudoku_solver.brute_force_solve_sudoku(board)
    assert (board.board_numbers == boards.solved_hard).all()
Beispiel #6
0
def solve_all_single_value_cells(sudoku: sudoku_board.Sudoku) -> None:
    solved_value = True
    while solved_value:
        solved_value = False
        for row in range(9):
            for column in range(9):
                values = get_possible_cell_values(sudoku, row, column)
                if len(values) == 1 and sudoku.board_numbers[row][column] == 0:
                    sudoku.add_cell(row, column, values[0])
                    solved_value = True
def test_find_empty_location():
    board = Sudoku(boards.unsolved_easy)
    location = [0, 0]
    empty = sudoku_solver.find_empty_location(board.board_numbers, location)
    assert empty

    board = Sudoku(boards.solved_easy)
    location = [0, 0]
    empty = sudoku_solver.find_empty_location(board.board_numbers, location)
    assert not empty
def test_crosshatch_box():
    sudoku_board = Sudoku(boards.unique_candidate_test)
    assert sudoku_board.board_numbers[7, 0] == 0
    sudoku_solver.crosshatch_box(sudoku_board, 6)
    assert sudoku_board.board_numbers[7, 0] == 4

    sudoku_board = Sudoku(boards.unsolved_hard)
    assert sudoku_board.board_numbers[5, 6] == 0
    sudoku_solver.crosshatch_box(sudoku_board, 5)
    assert sudoku_board.board_numbers[5, 6] == 8
def test_solve_board():
    board = Sudoku(boards.unsolved_easy)
    sudoku_solver.solve_board(board)
    assert sudoku_solver.verify_board(board)
    assert (board.board_numbers == boards.solved_easy).all()

    board = Sudoku(boards.unsolved_very_hard)
    sudoku_solver.solve_board(board)
    assert sudoku_solver.verify_board(board)
    assert (board.board_numbers == boards.solved_very_hard).all()

    board = Sudoku(boards.empty)
    sudoku_solver.solve_board(board)
    assert sudoku_solver.verify_board(board)
def test_used_in_box():
    board = Sudoku(boards.unsolved_easy)
    used = sudoku_solver.used_in_box(board.board_numbers, 0, 0, 5)
    assert used

    used = sudoku_solver.used_in_box(board.board_numbers, 0, 0, 1)
    assert not used
def test_check_location_is_safe():
    board = Sudoku(boards.unsolved_easy)
    safe = sudoku_solver.check_location_is_safe(board.board_numbers, 0, 0, 1)
    assert safe

    safe = sudoku_solver.check_location_is_safe(board.board_numbers, 0, 0, 5)
    assert not safe
def test_solve_naked_subset_column():
    column = 0
    row = 1
    sudoku_board = Sudoku(boards.naked_pair_test)
    assert sudoku_board.board_numbers[row, column] == 0
    sudoku_solver.solve_naked_subset_column(sudoku_board, column)
    assert sudoku_board.board_numbers[row, column] == 1
Beispiel #13
0
    def reset_clicked(self):
        board = boards.empty

        for row in range(9):
            for column in range(9):
                self.text_boxes[row][column].delete(0, tk.END)

        self.sudoku = Sudoku(board, self)
Beispiel #14
0
def crosshatch_box(sudoku: sudoku_board.Sudoku, box_number: int) -> bool:
    all_values = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    unused_values = []

    box = sudoku.get_box_from_index(box_number)
    box_values = box.flatten()

    for value in all_values:
        if value not in box_values:
            unused_values.append(value)

    solved_value = False
    # Loop through each value that is not in the box.
    for value in unused_values:
        possible_rows = []
        possible_columns = []

        # Check each row that goes through the box.
        for row in get_rows_from_box_index(box_number):
            # If the value is not in that row then it could be in that row of the box.
            if not check_row_for_value(sudoku, row, value):
                possible_rows.append(row)
        # Check each column that goes through the box.
        for column in get_columns_from_box_index(box_number):
            # If the value is not in that column then it could be in that column of the box.
            if not check_column_for_value(sudoku, column, value):
                possible_columns.append(column)

        # Remove duplicates from possible rows and columns.
        possible_rows = list(set(possible_rows))
        possible_columns = list(set(possible_columns))

        # A cell position is only possible if the value is 0. Save the index if it is.
        possible_index = []
        for row in possible_rows:
            for column in possible_columns:
                if sudoku.board_numbers[row, column] == 0:
                    possible_index.append([row, column])

        # If there is only one possible value for this cell then add it to the board.
        if len(possible_index) == 1:
            sudoku.add_cell(possible_index[0][0], possible_index[0][1], value)
            solved_value = True

    return solved_value
def test_get_possible_cell_values_with_unsolved_easy():
    sudoku_board = Sudoku(boards.unsolved_easy)

    possible_values = sudoku_solver.get_possible_cell_values(
        sudoku_board, 0, 2)
    assert possible_values == [1, 2, 4]

    possible_values = sudoku_solver.get_possible_cell_values(
        sudoku_board, 0, 1)
    assert possible_values == [3]

    possible_values = sudoku_solver.get_possible_cell_values(
        sudoku_board, 8, 8)
    assert possible_values == [9]
Beispiel #16
0
def solve_naked_subset_row(sudoku: sudoku_board.Sudoku, row: int) -> None:
    cell_possible_values = []
    for column in range(9):
        cell_possible_values.append(
            get_possible_cell_values(sudoku, row, column))

    subset_indices_two = []
    for cell in range(9):
        if len(cell_possible_values[cell]) == 2:
            subset_indices_two.append(cell)

    values_two = []
    if len(subset_indices_two) == 2:
        values_two = cell_possible_values[subset_indices_two[0]]

    for index in range(9):
        if index not in subset_indices_two:
            cell_possible_values[index] = (
                list(set(cell_possible_values[index]) - set(values_two)))

    for column in range(9):
        if len(cell_possible_values[column]) == 1:
            sudoku.add_cell(row, column, cell_possible_values[column][0])
Beispiel #17
0
def solve_board(sudoku: sudoku_board.Sudoku):
    iterations = 0
    while not verify_board(sudoku):
        iterations += 1
        solve_all_single_value_cells(sudoku)
        solve_all_crosshatch_boxes(sudoku)
        solve_all_naked_subsets(sudoku)

        if iterations == 5:
            if sudoku.gui is None:
                print("Could not find a solution after {0} iterations.".format(
                    iterations))
                print("Have solved the board to the following point...")
                sudoku.print_board()
                print("Will now try to brute force solve the board...")
            brute_force_solve_sudoku(sudoku)

    if verify_board(sudoku):
        if sudoku.gui is None:
            print(
                "Have completed the board with the following solution, after {0} iterations..."
                .format(iterations))
            sudoku.print_board()
    return
Beispiel #18
0
    def solve_clicked(self):
        board = boards.empty
        self.solve_button.config(state='disabled')
        self.reset_button.config(state='disabled')

        for row in range(9):
            for column in range(9):
                current_box = self.text_boxes[row][column]
                if str.isdigit(current_box.get()) and len(current_box.get()) == 1:
                    current_box.config(state='disabled')
                    board[row][column] = int(current_box.get())

        self.sudoku = Sudoku(board, self)
        try:
            sudoku_solver.solve_board(self.sudoku)
            self.reset_button.config(state='enabled')
            self.close_button.config(state='enabled')
        except tk.TclError:
            pass
Beispiel #19
0
def get_possible_cell_values(sudoku: sudoku_board.Sudoku, row: int,
                             column: int) -> List[int]:
    all_values = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    possible_values = []

    if sudoku.board_numbers[row][column] != 0:
        possible_values.append(sudoku.board_numbers[row][column])
    else:
        row_values = sudoku.board_numbers[row, :].flatten()
        column_values = sudoku.board_numbers[:, column].flatten()
        box_values = sudoku.get_box_from_cell(row, column).flatten()

        used_values = unique(
            list(filter(non_zero, chain(row_values, column_values,
                                        box_values))))

        for value in all_values:
            if value not in used_values:
                possible_values.append(value)

    return possible_values
def test_get_box_from_cell_with_valid():
    sudoku_board = Sudoku(boards.unsolved_easy)

    box1 = sudoku_board.get_box_from_cell(0, 0)
    expected_box1 = array([[5, 3, 0], [6, 0, 0], [0, 9, 8]])
    assert (box1 == expected_box1).all()

    box2 = sudoku_board.get_box_from_cell(1, 3)
    expected_box2 = array([[0, 7, 0], [1, 9, 5], [0, 0, 0]])
    assert (box2 == expected_box2).all()

    box6 = sudoku_board.get_box_from_cell(3, 8)
    expected_box6 = array([[0, 0, 3], [0, 0, 1], [0, 0, 6]])
    assert (box6 == expected_box6).all()

    box7 = sudoku_board.get_box_from_cell(8, 2)
    expected_box7 = array([[0, 6, 0], [0, 0, 0], [0, 0, 0]])
    assert (box7 == expected_box7).all()

    box9 = sudoku_board.get_box_from_cell(6, 6)
    expected_box9 = array([[2, 8, 0], [0, 0, 5], [0, 7, 9]])
    assert (box9 == expected_box9).all()
def test_solve_all_single_value_cells_with_unsolved_easy():
    sudoku_board = Sudoku(boards.unsolved_easy)
    sudoku_solver.solve_all_single_value_cells(sudoku_board)
    solved_board = sudoku_board.board_numbers
    expected_board = boards.solved_easy
    assert (array(expected_board) == solved_board).all()
def test_verify_row_with_valid_rows():
    sudoku_board = Sudoku(boards.solved)
    for i in range(9):
        assert sudoku_solver.verify_row(sudoku_board, i)
def test_verify_board_with_invalid():
    sudoku_board = Sudoku(boards.invalid)
    assert not sudoku_solver.verify_board(sudoku_board)
def test_verify_board_with_valid():
    sudoku_board = Sudoku(boards.solved)
    assert sudoku_solver.verify_board(sudoku_board)
def test_solve_all_naked_subsets():
    sudoku_board = Sudoku(boards.naked_pair_test)
    sudoku_solver.solve_all_naked_subsets(sudoku_board)
    assert sudoku_board.board_numbers[0, 0] == 0
def test_check_column_for_value():
    sudoku = Sudoku(boards.unique_candidate_test)
    assert sudoku_solver.check_column_for_value(sudoku, 2, 4)
    assert not sudoku_solver.check_column_for_value(sudoku, 2, 5)
Beispiel #27
0
    parser.add_argument(
        "-f",
        "--fast",
        dest="solve_fast",
        help="Solve quickly without displaying values being added in.",
        default=False,
        action="store_true")

    args = parser.parse_args()
    if args.use_gui:
        gui = sudoku_gui.Gui()
        gui.solve_fast = args.solve_fast
        gui.window.mainloop()
    else:
        print("Welcome to Soduku solver...")
        correct = "no"
        sudoku = None
        while correct.strip() != "yes":
            print(
                "Please enter the Soduku board in rows of 9, separating numbers with a space."
            )
            print("Enter 0 for any number that is unknown.")
            board = read_board_in()
            sudoku = Sudoku(board)

            print("You entered the following board...")
            sudoku.print_board()
            print("Is that correct? (yes/no)")
            correct = input()
        sudoku_solver.solve_board(sudoku)
def test_verify_column_with_invalid_columns():
    sudoku_board = Sudoku(boards.invalid)
    for i in range(9):
        assert not sudoku_solver.verify_column(sudoku_board, i)
def test_verify_box_with_invalid_boxes():
    sudoku_board = Sudoku(boards.invalid)
    for i in range(9):
        assert not sudoku_solver.verify_box(sudoku_board, i)
def test_solve_all_crosshatch_boxes():
    sudoku_board = Sudoku(boards.unique_candidate_test)
    assert sudoku_board.board_numbers[7, 0] == 0
    sudoku_solver.solve_all_crosshatch_boxes(sudoku_board)
    assert sudoku_board.board_numbers[7, 0] == 4