def main():
    """The main entry point of the program."""
    argument_parser = build_argument_parser()
    arguments = argument_parser.parse_args()
    words, board = parse_puzzle(arguments.puzzle_file)
    arguments.puzzle_file.close()
    puzzle = Puzzle(board)
    print(format_results(puzzle.find_all(words), words))
 def setup_method(self, method):
     # Word list: dog, cat, pig
     # yapf: disable
     self.board = [
         ['x', 'd', 'o', 'g'],
         ['o', 'r', 't', 'i'],
         ['j', 'a', 'i', 'p'],
         ['c', 'l', 'm', 'q']
     ]
     # yapf: enable
     self.puzzle = Puzzle(self.board)
Exemple #3
0
class SolverIntegrationTest(unittest.TestCase):
    """Test the integration between the main application and the solver module.
    """

    # pylint: disable=unused-argument
    def setup_method(self, method):
        self.puzzle_file = open('./data/pillar-sample.puzzle')
        self.words, self.board = wordsearch.parse_puzzle(self.puzzle_file)
        self.puzzle = Puzzle(self.board)

    def teardown_method(self, method):
        self.puzzle_file.close()

    # pylint: enable=unused-argument

    def test_can_load_a_file_and_solve_the_puzzle(self):
        actual = self.puzzle.find_all(self.words)
        expected = {
            'BONES': [(6, 0), (7, 0), (8, 0), (9, 0), (10, 0)],
            'KHAN': [(9, 5), (8, 5), (7, 5), (6, 5)],
            'KIRK': [(7, 4), (7, 3), (7, 2), (7, 1)],
            'SCOTTY': [(5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)],
            'SPOCK': [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)],
            'SULU': [(3, 3), (2, 2), (1, 1), (0, 0)],
            'UHURA': [(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)]
        }
        assert expected == actual
 def test_raises_an_exception_if_the_board_is_not_square(self):
     # yapf: disable
     board = [
         ['a', 'b', 'c'],
         ['e', 'f'],
         ['g', 'h', 'i']
     ]
     # yapf: enable
     with pytest.raises(ValueError) as e:
         _ = Puzzle(board)
     assert str(e.value) == 'board is not square.'
Exemple #5
0
 def setup_method(self, method):
     self.puzzle_file = open('./data/pillar-sample.puzzle')
     self.words, self.board = wordsearch.parse_puzzle(self.puzzle_file)
     self.puzzle = Puzzle(self.board)
 def test_raises_an_exception_if_the_board_is_not_at_least_2x2(self):
     board = [['a']]
     with pytest.raises(ValueError) as e:
         _ = Puzzle(board)
     assert str(e.value) == 'board is too small; it must be at least 2x2.'
 def test_raises_an_exception_if_board_is_not_a_list(self):
     with pytest.raises(TypeError) as e:
         _ = Puzzle({})
     assert str(e.value) == 'board is not of type list.'
 def test_raises_an_exception_if_the_board_is_empty(self):
     with pytest.raises(ValueError) as e:
         _ = Puzzle([[]])
     assert str(e.value) == 'board is empty.'
class PuzzleTest(unittest.TestCase):

    # pylint: disable=unused-argument
    def setup_method(self, method):
        # Word list: dog, cat, pig
        # yapf: disable
        self.board = [
            ['x', 'd', 'o', 'g'],
            ['o', 'r', 't', 'i'],
            ['j', 'a', 'i', 'p'],
            ['c', 'l', 'm', 'q']
        ]
        # yapf: enable
        self.puzzle = Puzzle(self.board)

    # pylint: enable=unused-argument

    def test_raises_an_exception_if_the_board_is_null(self):
        with pytest.raises(ValueError) as e:
            _ = Puzzle(None)
        assert str(e.value) == 'board is empty.'

    def test_raises_an_exception_if_the_board_is_an_empty_list(self):
        with pytest.raises(ValueError) as e:
            _ = Puzzle([])
        assert str(e.value) == 'board is empty.'

    def test_raises_an_exception_if_the_board_is_empty(self):
        with pytest.raises(ValueError) as e:
            _ = Puzzle([[]])
        assert str(e.value) == 'board is empty.'

    def test_raises_an_exception_if_board_is_not_a_list(self):
        with pytest.raises(TypeError) as e:
            _ = Puzzle({})
        assert str(e.value) == 'board is not of type list.'

    def test_raises_an_exception_if_the_board_is_not_square(self):
        # yapf: disable
        board = [
            ['a', 'b', 'c'],
            ['e', 'f'],
            ['g', 'h', 'i']
        ]
        # yapf: enable
        with pytest.raises(ValueError) as e:
            _ = Puzzle(board)
        assert str(e.value) == 'board is not square.'

    def test_raises_an_exception_if_the_board_is_not_at_least_2x2(self):
        board = [['a']]
        with pytest.raises(ValueError) as e:
            _ = Puzzle(board)
        assert str(e.value) == 'board is too small; it must be at least 2x2.'

    def test_size_returns_the_width_and_height_as_a_tuple(self):
        assert (4, 4) == self.puzzle.size

    def test_height_returns_the_height_of_the_board(self):
        assert self.puzzle.height == 4

    def test_width_returns_the_width_of_the_board(self):
        assert self.puzzle.width == 4

    def test_all_positions_is_an_iterator_through_the_entire_board(self):
        positions = [position for position in self.puzzle.all_positions()]
        expected = [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2),
                    (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (3, 0), (3, 1),
                    (3, 2), (3, 3)]
        assert expected == positions

    def test_get_valid_moves_returns_a_list_of_valid_moves(self):
        current_position = (0, 0)
        moves = self.puzzle.get_valid_moves(current_position)
        assert wordsearch.solver.RIGHT in moves
        assert wordsearch.solver.DOWN in moves
        assert wordsearch.solver.DOWN_RIGHT in moves

    def test_get_valid_moves_does_not_return_invalid_moves(self):
        current_position = (3, 3)
        moves = self.puzzle.get_valid_moves(current_position)
        assert wordsearch.solver.RIGHT not in moves
        assert wordsearch.solver.DOWN not in moves
        assert wordsearch.solver.DOWN_RIGHT not in moves

    def test_get_valid_moves_projects_multiple_spaces(self):
        current_position = (0, 0)
        moves = self.puzzle.get_valid_moves(current_position, distance=3)
        assert (0, 3) in moves
        assert (3, 0) in moves
        assert (3, 3) in moves

        current_position = (2, 1)
        moves = self.puzzle.get_valid_moves(current_position, distance=3)
        assert not moves

        current_position = (2, 1)
        moves = self.puzzle.get_valid_moves(current_position, distance=2)
        assert len(moves) == 3
        assert (0, 1) in moves
        assert (2, 3) in moves
        assert (0, 3) in moves

        current_position = (3, 3)
        moves = self.puzzle.get_valid_moves(current_position, distance=3)
        assert (0, 0) in moves
        assert (0, 3) in moves
        assert (3, 0) in moves

    def test_get_valid_moves_raises_error_if_distance_is_zero_or_negative(
            self):
        with pytest.raises(ValueError) as e:
            self.puzzle.get_valid_moves((0, 0), distance=-1)
        assert str(e.value) == 'distance must be at least 1.'

    def test_get_valid_moves_raises_error_if_position_is_out_of_bounds(self):
        with pytest.raises(IndexError) as e:
            self.puzzle.get_valid_moves((-1, 0), distance=1)
        assert str(e.value) == 'starting position out of bounds.'

        with pytest.raises(IndexError) as e:
            self.puzzle.get_valid_moves((0, -1), distance=1)
        assert str(e.value) == 'starting position out of bounds.'

        with pytest.raises(IndexError) as e:
            self.puzzle.get_valid_moves((4, 3), distance=1)
        assert str(e.value) == 'starting position out of bounds.'

        with pytest.raises(IndexError) as e:
            self.puzzle.get_valid_moves((3, 4), distance=1)
        assert str(e.value) == 'starting position out of bounds.'

    def test_get_direction_returns_the_direction_from_origin_to_target(self):
        direction = self.puzzle.get_direction((3, 0), (0, 3))
        assert wordsearch.solver.UP_RIGHT == direction

        direction = self.puzzle.get_direction((0, 0), (1, 1))
        assert wordsearch.solver.DOWN_RIGHT == direction

    def test_get_direction_returns_zero_zero_if_target_is_origin(self):
        assert (0, 0) == self.puzzle.get_direction((2, 2), (2, 2))

    def test_get_direction_raises_error_if_origin_is_out_of_bounds(self):
        with pytest.raises(IndexError) as e:
            self.puzzle.get_direction((-1, 0), (2, 2))
        assert str(e.value) == 'origin is out of bounds.'

    def test_get_characters_returns_characters_in_the_given_range(self):
        characters, _ = self.puzzle.get_characters((0, 1), (0, 3))
        assert ''.join(characters) == 'dog'

        characters, _ = self.puzzle.get_characters((2, 3), (0, 3))
        assert ''.join(characters) == 'pig'

        characters, _ = self.puzzle.get_characters((3, 0), (1, 2))
        assert ''.join(characters) == 'cat'

    def test_get_characters_returns_the_positions_in_the_given_range(self):
        _, positions = self.puzzle.get_characters((0, 1), (0, 3))
        assert [(0, 1), (0, 2), (0, 3)] == positions

        _, positions = self.puzzle.get_characters((2, 3), (0, 3))
        assert [(2, 3), (1, 3), (0, 3)] == positions

        _, positions = self.puzzle.get_characters((3, 0), (1, 2))
        assert [(3, 0), (2, 1), (1, 2)] == positions

    def test_get_characters_raises_error_if_position_out_of_bounds(self):
        with pytest.raises(IndexError) as e:
            self.puzzle.get_characters((-1, 0), (2, 0))
        assert str(e.value) == 'starting position out of bounds.'

    def test_get_characters_raises_error_if_target_out_of_bounds(self):
        with pytest.raises(IndexError) as e:
            self.puzzle.get_characters((2, 0), (-1, 0))
        assert str(e.value) == 'target position out of bounds.'

    def test_find_returns_an_empty_list_if_the_word_cannot_be_found(self):
        assert [] == self.puzzle.find('cow')

    def test_find_returns_the_positions_of_the_characters_in_the_word(self):
        assert [(0, 1), (0, 2), (0, 3)] == self.puzzle.find('dog')
        assert [(2, 3), (1, 3), (0, 3)] == self.puzzle.find('pig')
        assert [(3, 0), (2, 1), (1, 2)] == self.puzzle.find('cat')

    def test_find_raises_value_error_if_word_is_null(self):
        with pytest.raises(ValueError) as e:
            self.puzzle.find(None)
        assert str(e.value) == 'the specified word is None.'

    def test_find_raises_value_error_when_word_is_larger_than_puzzle(self):
        word = 'moose'
        with pytest.raises(ValueError) as e:
            self.puzzle.find(word)
        assert str(e.value) == \
            'the specified word (%s) is larger than the board.' % word

    def test_find_raises_value_error_when_word_is_too_short(self):
        with pytest.raises(ValueError) as e:
            self.puzzle.find('d')
        assert str(e.value) == 'the specified word (%s) is too short.' % 'd'

    def test_find_raises_type_error_if_word_is_not_a_str(self):
        word = ['c', 'a', 't']
        with pytest.raises(TypeError) as e:
            self.puzzle.find(word)
        assert str(e.value) == 'the specified word is not of type str.'

    def test_find_all_returns_an_empty_dict_if_no_words_could_be_found(self):
        assert {} == self.puzzle.find_all(['cow'])

    def test_find_all_retuns_a_dict_with_the_positions_of_each_word(self):
        words = ['dog', 'cat', 'pig']
        expected = {
            'dog': [(0, 1), (0, 2), (0, 3)],
            'cat': [(3, 0), (2, 1), (1, 2)],
            'pig': [(2, 3), (1, 3), (0, 3)]
        }
        assert expected == self.puzzle.find_all(words)

    def test_find_all_raises_value_error_when_words_is_null(self):
        with pytest.raises(ValueError) as e:
            self.puzzle.find_all(None)
        assert str(e.value) == 'the specified list of words is None.'

    def test_find_all_raises_type_error_if_words_is_not_a_list(self):
        words = ('cat', 'dog', 'pig')
        with pytest.raises(TypeError) as e:
            self.puzzle.find_all(words)
        assert str(e.value) == \
            'expected words to be of type list, but got (%s)' % type(words)