Example #1
0
def test_peers() -> None:
    """Peers for non diagonal board for 'A1'"""
    peer = 'A1'
    a1_peers = ['A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'B1', 'B2',
                'B3', 'C1', 'C2', 'C3', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1']
    board = SB()
    assert board.peers(peer) == set(a1_peers)
Example #2
0
def test_performance_beta(board_size):
    """
    Tests time performance of local hill climbing using restarts
    Displays the results
    :param board_size: size of a board to test on
    """
    # init test board
    board = Board(size=board_size)
    print(
        f'\nTesting overall time performance of beta hill climbing with board of size {board_size}:'
    )
    if not board.set_init_state():
        print('Failed to load the board, quitting..')
        return

    # measure times
    solver = CustomBetaHC(board,
                          1,
                          MAX_ITER_BETA_STATIC,
                          N_PROB_STATIC,
                          BETA_PROB_STATIC,
                          stop_if_found=True)
    times = _engine.test_time_perfect(solver, SOLUTIONS_NUM)

    # print results
    _print_times(*times)
Example #3
0
def test_beta_prob(board_size):
    """
    Tests beta probability for beta hill climbing
    Displays the results
    :param board_size: size of a board to test on
    """
    # init test board
    board = Board(size=board_size)
    print(
        f'\nTesting steps distribution for basic hill climb with board of size {board_size}:'
    )
    if not board.set_init_state():
        print('Failed to load the board, quitting..')
        return

    # start with probability of 30% and decrease
    beta = 0.3
    while True:
        print(f'[beta probability = {beta:.2f}]:')
        # analyze current steps distribution
        solver = CustomBetaHC(board, RESTARTS_BETA_STATIC,
                              MAX_ITER_BETA_STATIC, N_PROB_STATIC, beta)
        # print the result
        _print_analysis(_engine.analyze_solver(solver))
        # update beta
        beta = beta - 0.2 if beta > 0.1 else beta - 0.01
        beta = round(beta, 2)
        if beta < 0.01:
            break
Example #4
0
	def test_value1(self):
		board = Board([[None]*Board.COLS]*Board.ROWS)
		res = 	([[0,0,0,1,1,1,2,2,2]]*3 +
				[[3,3,3,4,4,4,5,5,5]]*3 +
				[[6,6,6,7,7,7,8,8,8]]*3)
		for i in range(Board.ROWS):
			for j in range(Board.COLS):
				assert_equal(board.getGridIndex(i,j),res[i][j])
Example #5
0
def test_peers_diagonal() -> None:
    """Peers for diagonal board for 'A1'"""
    peer = 'A1'
    a1_peers = ['A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'B1', 'B2',
                'B3', 'C1', 'C2', 'C3', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1',
                'I9', 'H8', 'D4', 'E5', 'F6', 'G7']
    board = SB(diagonal_mode=True)
    assert board.peers(peer) == set(a1_peers)
Example #6
0
 def test_value1(self):
     board = Board([[None] * Board.COLS] * Board.ROWS)
     res = ([[0, 0, 0, 1, 1, 1, 2, 2, 2]] * 3 +
            [[3, 3, 3, 4, 4, 4, 5, 5, 5]] * 3 +
            [[6, 6, 6, 7, 7, 7, 8, 8, 8]] * 3)
     for i in range(Board.ROWS):
         for j in range(Board.COLS):
             assert_equal(board.getGridIndex(i, j), res[i][j])
Example #7
0
class TestBoard(TestCase):
    def setUp(self):
        self.matrix = [
            9, 0, 0,  0, 8, 0,  3, 0, 0,
            0, 0, 0,  2, 5, 0,  7, 0, 0,
            0, 2, 0,  3, 0, 0,  0, 0, 4,
            0, 9, 4,  0, 0, 0,  0, 0, 0,
            0, 0, 0,  7, 3, 0,  5, 6, 0,
            7, 0, 5,  0, 6, 0,  4, 0, 0,
            0, 0, 7,  8, 0, 3,  9, 0, 0,
            0, 0, 1,  0, 0, 0,  0, 0, 3,
            3, 0, 0,  0, 0, 0,  0, 0, 2,
        ]
        self.board = Board(self.matrix)
        self.row0 = [9, 0, 0, 0, 8, 0, 3, 0, 0]
        self.column0 = [9, 0, 0, 0, 0, 7, 0, 0, 3]

    def test_get_cell(self):
        assert 9 == self.board.get_cell(0, 0)
        assert 3 == self.board.get_cell(0, 8)
        assert 2 == self.board.get_cell(8, 8)

    def test_get_column(self):
        assert self.column0 == self.board.get_column(0)

    def test_columns(self):
        columns = list(self.board.columns)
        assert 9 == len(columns)
        assert self.column0 == columns[0]

    def test_get_row(self):
        assert self.row0 == self.board.get_row(0)

    def test_rows(self):
        rows = list(self.board.rows)
        assert 9 == len(rows)
        assert self.row0 == rows[0]

    def test_squares(self):
        square00 = [9, 0, 0,
                    0, 0, 0,
                    0, 2, 0]
        squares = list(self.board.squares)
        assert 9 == len(squares)
        assert square00 == squares[0]

    def get_square_by_cell(self):
        square00 = [9, 0, 0,
                    0, 0, 0,
                    0, 2, 0]

        square22 = [8, 0, 3,
                    0, 0, 0,
                    0, 0, 0]

        assert square00 == self.board.get_square_by_cell(2, 2)
        assert square22 == self.board.get_square_by_cell(7, 8)
Example #8
0
def test_reduce_puzzle_fail() -> None:
    """Given an empty board reduce will fail and return none"""
    board_string = '.' * SB.num_boxes()
    board = SB.grid_values(board_string)

    sbrd = SB()
    solution = sbrd.reduce_puzzle(board)

    assert solution is None
Example #9
0
def test_diagonal() -> None:
    diagonal_grid = ('2.............62....1....7...6..8...3...9...7...6..4...4'
                     '....8....52.............3')
    sbrd = SB(diagonal_mode=True)
    board = sbrd.grid_values(diagonal_grid)

    result = sbrd.search(board)

    assert result == solved_diag_sudoku
Example #10
0
def test_display_board(capsys: Any) -> None:
    """Ensure display method prints ascii board correctly"""
    board_string = ('483921657967345821251876493548132976729564138136798245'
                    '372689514814253769695417382')
    # display stdout for printing sudoku board
    with capsys.disabled():
        print('\n')
        SB.display(SB.grid_values(board_string))
        print('\n')
Example #11
0
def test_validate() -> None:
    """Validation function correctly validates complete board"""
    board_string = ('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82..'
                    '..26.95..8..2.3..9..5.1.3..')
    board = SB.grid_values(board_string)
    sbrd = SB()
    solution = sbrd.reduce_puzzle(board)
    valid = sbrd.validate(solution)

    assert valid is True
Example #12
0
def test_diagonal() -> None:
    """Solve problem with diagonal constraint enabled"""
    diagonal_grid = ('2.............62....1....7...6..8...3...9...7...6..4...4'
                     '....8....52.............3')
    sbrd = SB(diagonal_mode=True)
    board = sbrd.grid_values(diagonal_grid)

    result = sbrd.search(board)

    assert result == solved_diag_sudoku
Example #13
0
def test_naked_multi_4() -> None:
    quad_board = naked_multi_board_1.copy()

    quad_board['A1'] = quad_board['A1'] + '2'  # give it a 2 to clear
    quad_board['A5'] = quad_board['A5'] + '2'  # give it a 2 to clear
    quad_board['F1'] = quad_board['F1'] + '1'  # give it a 1 to clear

    sbrd = SB()
    board = sbrd.naked_multi(quad_board, 4)
    assert board == naked_multi_board_1
Example #14
0
def test_validate_fail() -> None:
    """Validation function correctly fails on incomplete board"""
    board_string = ('4.....8.5.3..........7......2.....6.....8.4......1.......'
                    '6.3.7.5..2.....1.4......')
    board = SB.grid_values(board_string)
    sbrd = SB()
    solution = sbrd.reduce_puzzle(board)
    valid = sbrd.validate(solution)

    assert valid is False
Example #15
0
def test_naked_multi_3() -> None:
    """Solve first naked twin board with naked triplets"""
    triplet_board = naked_multi_board_1.copy()

    triplet_board['A5'] = triplet_board['A5'] + '3'  # give it a 3 to clear
    triplet_board['I2'] = triplet_board['I2'] + '7'  # give it a 7 to clear
    triplet_board['G2'] = triplet_board['G2'] + '3'  # give it a 3 to clear

    sbrd = SB()
    board = sbrd.naked_multi(triplet_board, 3)
    assert board == naked_multi_board_1
Example #16
0
def test_board_to_str() -> None:
    """Ensure board dictionary to comma string is correct"""
    board_string = ('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82..'
                    '..26.95..8..2.3..9..5.1.3..')
    str_list = list(board_string)
    str_list = list(item.replace('.', '123456789') for item in str_list)
    expected_string = ','.join(str_list)

    board = SB.grid_values(board_string)
    string = SB.board_to_str(board)
    assert string == expected_string
Example #17
0
def test_naked_multi_3() -> None:
    """Solve first naked twin board with naked triplets"""
    triplet_board = naked_multi_board_1.copy()

    # add some numbers to the board that the existing triples can clear
    triplet_board['A5'] = triplet_board['A5'] + '3'  # give it a 3 to clear
    triplet_board['I2'] = triplet_board['I2'] + '7'  # give it a 7 to clear
    triplet_board['G2'] = triplet_board['G2'] + '3'  # give it a 3 to clear

    sbrd = SB()
    board = sbrd.naked_multi(triplet_board, 3)
    assert board == naked_multi_board_1
Example #18
0
def test_naked_multi_4() -> None:
    """Solve first naked twin board with naked quads"""
    quad_board = naked_multi_board_1.copy()

    # add some numbers to the board that the existing quads can clear
    quad_board['A1'] = quad_board['A1'] + '2'  # give it a 2 to clear
    quad_board['A5'] = quad_board['A5'] + '2'  # give it a 2 to clear
    quad_board['F1'] = quad_board['F1'] + '1'  # give it a 1 to clear

    sbrd = SB()
    board = sbrd.naked_multi(quad_board, 4)
    assert board == naked_multi_board_1
Example #19
0
def test_reduce_puzzle() -> None:
    """Ensure board state after recursive reduce is correct"""
    board_string = ('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82..'
                    '..26.95..8..2.3..9..5.1.3..')
    expected_string = ('4,8,3,9,2,1,6,5,7,9,6,7,3,4,5,8,2,1,2,5,1,8,7,6,4,9,3,'
                       '5,4,8,1,3,2,9,7,6,7,2,9,5,6,4,1,3,8,1,3,6,7,9,8,2,4,5,'
                       '3,7,2,6,8,9,5,1,4,8,1,4,2,5,3,7,6,9,6,9,5,4,1,7,3,8,2')

    board = SB.grid_values(board_string)
    sbrd = SB()
    solution = sbrd.reduce_puzzle(board)
    solution_string = sbrd.board_to_str(solution)
    assert solution_string == expected_string
Example #20
0
    def _beta_operator(self, board: Board):
        """
        ß-operator of the ß-climbing, introduces exploration to the algorithm
        :param board: Neighbouring state of the board
        :return: New state of the board
        """
        values = board.values()
        # scan the board
        for pos in board.unfilled_positions():
            # regenerate the value if it meets the probability of beta
            if self._with_probability(self._beta_prob):
                values[pos.y, pos.x] = self._generate_fill_number()
        # fill the board
        board.fill_board(values)

        return board
Example #21
0
    def _step(self, board: Board) -> Board:
        """
        Performs one hill climb step
        :param board: Current state of the board to step from
        :return: Board after the step
        """
        # select random line from unfilled ones
        unfilled = board.unfilled_by_row()
        row = list(unfilled.keys())[random.randint(0, len(unfilled) - 1)]
        line = board.values()[row]
        # swap 2 characters in it
        self._swap_in_line(line, unfilled[row])
        # update original board
        board.fill_line(row, line)

        return board
Example #22
0
def test_only_choice() -> None:
    """Ensure board state after single only choice is correct"""
    board_string = ('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82..'
                    '..26.95..8..2.3..9..5.1.3..')

    expected_string = ('45,8,3,9,2,1,6,5789,57,9,6,47,3,4,5,8,278,1,2,257,1,8,'
                       '7,6,4,23579,2357,345,345,8,1,3456,2,9,34567,34567,7,2,'
                       '9,5,34569,4,1,13456,8,1345,13459,6,7,3459,8,2,1345,'
                       '345,134,1347,2,6,8,9,5,1478,47,8,1467,47,2,5,3,17,6,9,'
                       '6,9,5,4,1,7,3,8,2')
    board_dict = SB.grid_values(board_string)
    sbrd = SB()
    eliminated_board = sbrd.eliminate(board_dict)
    only_choice_board = sbrd.only_choice(eliminated_board)
    only_choice_string = SB.board_to_str(only_choice_board)
    assert only_choice_string == expected_string
Example #23
0
def test_diagonal_units() -> None:
    """Ensure diagonal units are the correct ones"""
    units = [['A1', 'B2', 'C3', 'D4', 'E5', 'F6', 'G7', 'H8', 'I9'],
             ['I1', 'H2', 'G3', 'F4', 'E5', 'D6', 'C7', 'B8', 'A9']]
    # pylint: disable=protected-access
    diagonal_units = SB._diagonal_units()
    assert diagonal_units == units
Example #24
0
def test_remove_values_in_boxes() -> None:
    """Ensure removal of values from boxes"""
    board_dict = {'A1': '123', 'A2': '123'}
    expected_dict = {'A1': '3', 'A2': '123'}
    # pylint: disable=protected-access
    board = SB._remove_values_in_boxes(board_dict, set('1') | set('2'), ['A1'])
    assert board == expected_dict
Example #25
0
def test_eliminate() -> None:
    """Ensure board state after single elimination is correct"""
    board_string = ('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82..'
                    '..26.95..8..2.3..9..5.1.3..')

    # eliminated board in comma separated format for easy comparison
    expected_string = ('45,4578,3,49,2,147,6,5789,57,9,24678,47,3,47,5,78,278,'
                       '1,25,257,1,8,79,6,4,23579,2357,345,345,8,1,3456,2,9,'
                       '34567,34567,7,123459,49,459,34569,4,1,13456,8,1345,'
                       '13459,6,7,3459,8,2,1345,345,134,1347,2,6,478,9,5,1478,'
                       '47,8,1467,47,2,457,3,17,1467,9,46,4679,5,4,1,47,3,'
                       '24678,2467')
    board = SB.grid_values(board_string)
    eliminated_board = SB().eliminate(board)
    eliminated_string = SB.board_to_str(eliminated_board)

    assert eliminated_string == expected_string
Example #26
0
 def setUp(self):
     self.matrix = [
         1, 2, 0, 4,
         3, 4, 0, 0,
         2, 1, 0, 4,
         4, 4, 1, 3,
     ]
     self.board = Board(self.matrix)
Example #27
0
def test_diagonal_board() -> None:
    """Ensure diagonal board mode boolean constructor works"""
    sbrd = SB()
    sbrd_diagonal = SB(diagonal_mode=True)
    assert sbrd.all_units() != sbrd_diagonal.all_units()
    # pylint: disable=protected-access
    assert sbrd.all_units() + SB._diagonal_units() == sbrd_diagonal.all_units()
Example #28
0
 def setUp(self):
     self.matrix = [
         1, 2, 0, 4,
         3, 4, 0, 0,
         2, 1, 0, 4,
         4, 3, 4, 3,
     ]
     self.board = Board(self.matrix)
     self.rules = RuleHandler()
Example #29
0
class TestRulesHandler(TestCase):
    def setUp(self):
        self.matrix = [
            1, 2, 0, 4,
            3, 4, 0, 0,
            2, 1, 0, 4,
            4, 3, 4, 3,
        ]
        self.board = Board(self.matrix)
        self.rules = RuleHandler()

    def test_rules(self):
        cell = self.board.get_cell(1, 1)
        assert self.rules.is_valid(self.board, cell)
        cell = self.board.get_cell(1, 2)
        assert self.rules.is_valid(self.board, cell)
        cell = self.board.get_cell(2, 3)
        assert not self.rules.is_valid(self.board, cell)
Example #30
0
    def _neighbouring_operator(self, board: Board):
        """
        N-operator of the ß-climbing, introduces exploitation to the algorithm
        :param board: State of the board
        :return: Neighbouring state
        """
        values = board.values()

        # iterate modifiable tiles
        for pos in board.unfilled_positions():
            # modify the tile if it meets the probability of n
            if self._with_probability(self._n_prob):
                values[pos.y, pos.x] = self._neighbouring_val(values[pos.y,
                                                                     pos.x])
        # fill the board
        board.fill_board(values)

        return board
Example #31
0
def test_reduce_puzzle_incomplete() -> None:
    """Ensure given a more complex puzzle reduce terminates incomplete"""
    board_string = ('4.....8.5.3..........7......2.....6.....8.4......1.......'
                    '6.3.7.5..2.....1.4......')
    expected_string = ('4,1679,12679,139,2369,269,8,1239,5,26789,3,1256789,'
                       '14589,24569,245689,12679,1249,124679,2689,15689,'
                       '125689,7,234569,245689,12369,12349,123469,3789,2,'
                       '15789,3459,34579,4579,13579,6,13789,3679,15679,15679,'
                       '359,8,25679,4,12359,12379,36789,4,56789,359,1,25679,'
                       '23579,23589,23789,289,89,289,6,459,3,1259,7,12489,5,'
                       '6789,3,2,479,1,69,489,4689,1,6789,4,589,579,5789,'
                       '23569,23589,23689')

    board = SB.grid_values(board_string)
    sbrd = SB()
    solution = sbrd.reduce_puzzle(board)
    solution_string = sbrd.board_to_str(solution)
    assert solution_string == expected_string
Example #32
0
def main():
	board = Board(readSudokuFile('input.txt'))
	solver = Solver(board)
	solver.solve()
	#print "Final --"
	#print repr(board)
	print "-----"
	solver.solve()
	print board
Example #33
0
    def _beta_operator(self, board: Board):
        """
        ß-operator of the ß-climbing, introduces exploration to the algorithm
        :param board: Neighbouring state of the board
        :return: New state of the board
        """
        # go through modifiable rows
        unfilled = board.unfilled_by_row()
        for row in unfilled:
            # regenerate the row with probability of beta
            if self._with_probability(self._beta_prob):
                line = board.values()[row]
                # clear
                for index in unfilled[row]:
                    line[index] = 0
                # refill
                board.fill_line(row, np.array(self._fill_line_unique(line)))

        return board
Example #34
0
    def _neighbouring_operator(self, board: Board):
        """
        N-operator of the ß-climbing, introduces exploitation to the algorithm
        :param board: State of the board
        :return: Neighbouring state
        """
        values = board.values()

        # iterate rows
        unfilled = board.unfilled_by_row()
        for row in unfilled:
            # only modify the rows when they meet the probability of n
            if self._with_probability(self._n_prob):
                # swap 2 tiles
                self._swap_in_line(values[row], unfilled[row])
        # update original board
        board.fill_board(values)

        return board
Example #35
0
	def test_invalid(self):
		print "------"
		board = Board(readSudokuFile("test-input/test-invalid1.txt"))
		print "Board:"
		print board
		print "Checking for: ", repr(board[(0,6)]), "$"
		res = Solver.getAffectedFilledCells(board,board[(0,6)])
		print "Final:", repr(res)
		if len(set(res)) != len(res):
			raise InvalidSudokuStateError("Cell @" + repr(cell))
		print "-------"
		#No asserts, stdout check
Example #36
0
class TestRules(TestCase):
    def setUp(self):
        self.matrix = [
            1, 2, 0, 4,
            3, 4, 0, 0,
            2, 1, 0, 4,
            4, 4, 1, 3,
        ]
        self.board = Board(self.matrix)

    def test_unique_in_row(self):
        cell = self.board.get_cell(1, 0)
        assert unique_in_row(self.board, cell)
        cell = self.board.get_cell(1, 3)
        assert not unique_in_row(self.board, cell)

    def test_unique_in_column(self):
        cell = self.board.get_cell(0, 1)
        assert unique_in_column(self.board, cell)
        cell = self.board.get_cell(3, 0)
        assert not unique_in_column(self.board, cell)

    def test_unique_in_square(self):
        cell = self.board.get_cell(1, 1)
        assert unique_in_square(self.board, cell)
        cell = self.board.get_cell(0, 3)
        assert not unique_in_square(self.board, cell)
Example #37
0
 def __init__(self, puzzle, slow):
     """
     Constructor for the Solver class. The key members of this class are:
       finished: Flag to track if solution is found.
       board: Board object. This enforces the rules of Sudoku.
       moves: Track what moves have been tried so that they can be rolled
              back.
     The remaining members support display options.
     """
     self.iteration = 0
     self.finished = False
     self.slow = slow
     self.board = Board.factory(puzzle, slow)
     self.moves = [Move() for i in xrange(81)]
Example #38
0
 def setUp(self):
     self.matrix = [
         9, 0, 0,  0, 8, 0,  3, 0, 0,
         0, 0, 0,  2, 5, 0,  7, 0, 0,
         0, 2, 0,  3, 0, 0,  0, 0, 4,
         0, 9, 4,  0, 0, 0,  0, 0, 0,
         0, 0, 0,  7, 3, 0,  5, 6, 0,
         7, 0, 5,  0, 6, 0,  4, 0, 0,
         0, 0, 7,  8, 0, 3,  9, 0, 0,
         0, 0, 1,  0, 0, 0,  0, 0, 3,
         3, 0, 0,  0, 0, 0,  0, 0, 2,
     ]
     self.board = Board(self.matrix)
     self.row0 = [9, 0, 0, 0, 8, 0, 3, 0, 0]
     self.column0 = [9, 0, 0, 0, 0, 7, 0, 0, 3]
Example #39
0
# This file is part of Pydoku.
# 
# Pydoku is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# Pydoku is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Pydoku.  If not, see <http://www.gnu.org/licenses/>.

import os
from sudoku.board import Board

board = Board("board6.txt")

n = board.pre_solve()
print board
board.solve()
print board

board.fields


# 0.143
Example #40
0
	def test_getCellsInGrid(self):
		board = Board(readSudokuFile("test-input/test-input.txt"))
		for i in range(9):
			print "For %d"%i
			print repr(board.getCellsInGrid(i))