def main(): args = parse_args() if args.wordsearch: # Parse the specified wordsearch file board = Board([list(line.strip()) for line in args.wordsearch]) else: # Use a random board board = random_board(args.width, args.height) # Pickle trie for performance # The cache tracks the last modified time of the dictionary. # If there exists a pickle cache for the dictionary's name and the file has not been # changed since the last cache was made, load from the pickle cache instead. cache_name = args.dictionary.name + '.pickle' cache_valid = False #In case the cache file doesn't exist if os.path.exists(cache_name): lastmtime, rootnode = pickle.load(open(cache_name, 'rb')) cache_valid = lastmtime >= os.path.getmtime(args.dictionary.name) if not cache_valid: rootnode = TrieNode() for word in args.dictionary: rootnode.index(word.strip()) pickle.dump((os.path.getmtime(args.dictionary.name), rootnode), open(cache_name, 'wb')) for word in search_board(board, rootnode): if len(word) >= args.min_word_length: print(word)
def test_repr(self): node = TrieNode('a', children=[TrieNode('b'), TrieNode('c')]) regex = re.match( r"^TrieNode\(letter=a, children=\{([bc], [bc])\}, word_end=False\)$", repr(node)) self.assertFalse(regex == None) # Compare a set of the children so order doesn't matter self.assertEqual({w.strip() for w in regex.group(1).split(',')}, set(node.children))
def setUp(self): self.reference_root = TrieNode(children=[ TrieNode('a', children=[ TrieNode('m', children=[TrieNode('p', word_end=True) ]), TrieNode('c', children=[TrieNode('k', word_end=True)]) ]), TrieNode('b', children=[ TrieNode('u', children=[TrieNode('s', word_end=True)]) ]) ])
def test_search(self): root = TrieNode(words=['amp', 'ack', 'bus', 'bar']) board = Board([ ['z', 'a', 'm', 'x'], ['s', 'a', 'u', 'b'], ['u', 'm', 'c', 'a'], ['b', 'p', 'a', 'k'], ]) self.assertEqual(set(main.search_board(board, root)), {'amp', 'ack', 'bus'})
def test_init_children_or_words(self): self.assertRaises( ValueError, lambda: TrieNode(children=[TrieNode('a')], words=['b'])) try: TrieNode(children=[TrieNode('a')]) except ValueError: self.fail( "Should not get a ValueError when building TrieNode with only children." ) try: TrieNode(words=['foo']) except ValueError: self.fail( "Should not get a ValueError when building TrieNode with only words" ) try: TrieNode() except ValueError: self.fail( "Should not get a ValueError when building TrieNode with no children or words" )
def test_not_equal(self): self.assertFalse( recursive_equal(TrieNode(words=['amp', 'ack', 'bus']), TrieNode(words=['amm', 'ack', 'bus']))) self.assertFalse( recursive_equal(TrieNode(words=['am', 'ac', 'bus']), TrieNode(words=['amm', 'ack', 'bus']))) self.assertFalse( recursive_equal(TrieNode(words=['am', 'ac', 'bus']), TrieNode(words=['am', 'ack', 'bus', 'bar'])))
def test_not_equals(self): self.assertNotEqual(TrieNode(), TrieNode('a')) self.assertNotEqual(TrieNode(), TrieNode(children=[TrieNode('a')])) self.assertNotEqual(TrieNode('a'), TrieNode('b')) self.assertNotEqual(TrieNode(children=[TrieNode('a')]), TrieNode(children=[TrieNode('b')])) self.assertNotEqual(TrieNode('c', children=[TrieNode('a')]), TrieNode('d', children=[TrieNode('a')])) self.assertNotEqual(TrieNode('c', children=[TrieNode('a')]), TrieNode('c', children=[TrieNode('b')])) self.assertNotEqual(TrieNode('a'), TrieNode('a', word_end=True))
def test_root(self): root = TrieNode() self.assertEqual(root.children, {}) self.assertEqual(root.letter, None)
class TestTrie(unittest.TestCase): def setUp(self): self.reference_root = TrieNode(children=[ TrieNode('a', children=[ TrieNode('m', children=[TrieNode('p', word_end=True) ]), TrieNode('c', children=[TrieNode('k', word_end=True)]) ]), TrieNode('b', children=[ TrieNode('u', children=[TrieNode('s', word_end=True)]) ]) ]) def test_root(self): root = TrieNode() self.assertEqual(root.children, {}) self.assertEqual(root.letter, None) def test_equals(self): self.assertEqual(TrieNode(), TrieNode()) self.assertEqual(TrieNode('a'), TrieNode('a')) self.assertEqual(TrieNode(children=[TrieNode('a')]), TrieNode(children=[TrieNode('a')])) self.assertEqual(TrieNode('a', children=[TrieNode('b')]), TrieNode('a', children=[TrieNode('b')])) self.assertEqual(TrieNode('a', word_end=True), TrieNode('a', word_end=True)) def test_not_equals(self): self.assertNotEqual(TrieNode(), TrieNode('a')) self.assertNotEqual(TrieNode(), TrieNode(children=[TrieNode('a')])) self.assertNotEqual(TrieNode('a'), TrieNode('b')) self.assertNotEqual(TrieNode(children=[TrieNode('a')]), TrieNode(children=[TrieNode('b')])) self.assertNotEqual(TrieNode('c', children=[TrieNode('a')]), TrieNode('d', children=[TrieNode('a')])) self.assertNotEqual(TrieNode('c', children=[TrieNode('a')]), TrieNode('c', children=[TrieNode('b')])) self.assertNotEqual(TrieNode('a'), TrieNode('a', word_end=True)) def test_construct_with_children(self): root = TrieNode(children=[TrieNode('a'), TrieNode('b')]) self.assertEqual(root.letter, None) self.assertTrue('a' in root.children) self.assertEqual(root.children['a'], TrieNode('a')) def test_construct_with_children_other_iterator(self): root = TrieNode(children=(TrieNode('a'), TrieNode('b'))) self.assertEqual(root.letter, None) self.assertTrue('a' in root.children) self.assertEqual(root.children['a'], TrieNode('a')) def test_none_in_children(self): self.assertRaises(ValueError, lambda: TrieNode(children=[TrieNode()])) def test_lowers_letter(self): self.assertEqual(TrieNode('A'), TrieNode('a')) def test_only_one_letter(self): self.assertRaises(ValueError, lambda: TrieNode('ab')) def test_init_children_or_words(self): self.assertRaises( ValueError, lambda: TrieNode(children=[TrieNode('a')], words=['b'])) try: TrieNode(children=[TrieNode('a')]) except ValueError: self.fail( "Should not get a ValueError when building TrieNode with only children." ) try: TrieNode(words=['foo']) except ValueError: self.fail( "Should not get a ValueError when building TrieNode with only words" ) try: TrieNode() except ValueError: self.fail( "Should not get a ValueError when building TrieNode with no children or words" ) def test_index(self): root = TrieNode() root.index('amp', 'ack', 'bus') self.assertTrue(recursive_equal(root, self.reference_root)) def test_index_on_child(self): self.assertRaises( ValueError, lambda: self.reference_root.children['a'].index('foo')) def test_construct_with_words(self): root = TrieNode(words=['amp', 'ack', 'bus']) self.assertEqual(root, self.reference_root) def test_construct_with_words_other_iterator(self): root = TrieNode(words={'amp', 'ack', 'bus'}) self.assertEqual(root, self.reference_root) def test_construct_empty_wordlist(self): self.assertEqual(TrieNode(words=[]), TrieNode()) def test_full_does_contain(self): self.assertTrue(self.reference_root.contains('amp')) self.assertTrue(self.reference_root.contains('ack')) self.assertTrue(self.reference_root.contains('bus')) def test_partial_does_contain(self): self.assertFalse(self.reference_root.contains('a')) self.assertFalse(self.reference_root.contains('ac')) self.assertFalse(self.reference_root.contains('bu')) def test_partial_does_contain_prefix(self): self.assertTrue(self.reference_root.contains('a', prefix=True)) self.assertTrue(self.reference_root.contains('ac', prefix=True)) self.assertTrue(self.reference_root.contains('bu', prefix=True)) def test_does_not_contain(self): self.assertFalse(self.reference_root.contains('car')) self.assertFalse(self.reference_root.contains('candy')) self.assertFalse(self.reference_root.contains('amd')) self.assertFalse(self.reference_root.contains('adc')) self.assertFalse(self.reference_root.contains('bur')) self.assertFalse(self.reference_root.contains('apple')) def test_dunder_contains(self): self.assertTrue('amp' in self.reference_root) self.assertFalse('a' in self.reference_root) self.assertFalse('car' in self.reference_root) def test_repr(self): node = TrieNode('a', children=[TrieNode('b'), TrieNode('c')]) regex = re.match( r"^TrieNode\(letter=a, children=\{([bc], [bc])\}, word_end=False\)$", repr(node)) self.assertFalse(regex == None) # Compare a set of the children so order doesn't matter self.assertEqual({w.strip() for w in regex.group(1).split(',')}, set(node.children)) def test_add_chilren(self): root = TrieNode() root._add_children(TrieNode('a')) self.assertTrue('a' in root.children) self.assertEqual(root.children['a'], TrieNode('a'))
def test_equal(self): self.assertTrue( recursive_equal(TrieNode(words=['amp', 'ack', 'bus']), TrieNode(words=['amp', 'ack', 'bus'])))
def test_only_one_letter(self): self.assertRaises(ValueError, lambda: TrieNode('ab'))
def test_construct_empty_wordlist(self): self.assertEqual(TrieNode(words=[]), TrieNode())
def test_construct_with_words_other_iterator(self): root = TrieNode(words={'amp', 'ack', 'bus'}) self.assertEqual(root, self.reference_root)
def test_construct_with_words(self): root = TrieNode(words=['amp', 'ack', 'bus']) self.assertEqual(root, self.reference_root)
def test_index(self): root = TrieNode() root.index('amp', 'ack', 'bus') self.assertTrue(recursive_equal(root, self.reference_root))
def test_construct_with_children(self): root = TrieNode(children=[TrieNode('a'), TrieNode('b')]) self.assertEqual(root.letter, None) self.assertTrue('a' in root.children) self.assertEqual(root.children['a'], TrieNode('a'))
def test_none_in_children(self): self.assertRaises(ValueError, lambda: TrieNode(children=[TrieNode()]))
def test_construct_with_children_other_iterator(self): root = TrieNode(children=(TrieNode('a'), TrieNode('b'))) self.assertEqual(root.letter, None) self.assertTrue('a' in root.children) self.assertEqual(root.children['a'], TrieNode('a'))
def test_lowers_letter(self): self.assertEqual(TrieNode('A'), TrieNode('a'))
def setUp(self): self.reference_trie = TrieNode(words=['amp', 'amps', 'ack', 'bus']) self.search = main.start_trie_search(self.reference_trie) next(self.search)
def test_add_chilren(self): root = TrieNode() root._add_children(TrieNode('a')) self.assertTrue('a' in root.children) self.assertEqual(root.children['a'], TrieNode('a'))