Skip to content

Commit 8594ed9

Browse files
committed
[Feature] Added generating word squares.
1 parent bcb2a33 commit 8594ed9

File tree

4 files changed

+64
-2
lines changed

4 files changed

+64
-2
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,5 @@ Different algorithmic programs. Grouped by general topic.
8989
* [Reduce](algorithms/string/longest_common_prefix.py)
9090
* [Finding Substring](algorithms/string/rabin_karp_substring_search.py)
9191
* [Rabin-Karp](algorithms/string/rabin_karp_substring_search.py)
92-
* [Calculate Edit Distance](algorithms/string/edit_distance.py)
92+
* [Calculate Edit Distance](algorithms/string/edit_distance.py)
93+
* [Generate Word Squares](algorithms/string/word_squares.py)

algorithms/string/word_squares.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import structures
2+
from structures.trie import Trie
3+
4+
def word_squares(words):
5+
6+
trie = Trie(words)
7+
8+
def construct(square):
9+
if len(square) == len(square[0]):
10+
construct.squares.append(square)
11+
return
12+
# find prefix, based on len of square
13+
prefix = ""
14+
idx = len(square)
15+
for i in range(idx):
16+
prefix += square[i][idx]
17+
# get all prefix words
18+
prefix_words = trie.get_all_common_prefix(prefix)
19+
for prefix_word in prefix_words:
20+
construct(square + [prefix_word])
21+
22+
construct.squares = []
23+
24+
# start all squares
25+
for word in words:
26+
construct([word])
27+
28+
return construct.squares

structures/trie.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,24 @@ def add(self, word):
1414
current = self.head
1515
for letter in word:
1616
current = current.setdefault(letter, {})
17-
current[self.eof] = self.eof
17+
current[self.eof] = self.eof
18+
19+
def get_all_common_prefix(self, prefix):
20+
idx = 0
21+
node = self.head
22+
while idx < len(prefix):
23+
letter = prefix[idx]
24+
if letter not in node:
25+
return []
26+
node = node[letter]
27+
idx += 1
28+
# get all words after this node
29+
def getWords(node, prefix):
30+
if self.eof in node:
31+
return [prefix]
32+
words = []
33+
for key, val in node.items():
34+
words.extend(getWords(val, prefix + key))
35+
return words
36+
37+
return getWords(node, prefix)

tests/test_word_squares.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import unittest
2+
from algorithms.string.word_squares import word_squares
3+
4+
class TestWordSquares(unittest.TestCase):
5+
6+
def test_word_squares_basic(self):
7+
self.assertEqual([['baba', 'abat', 'baba', 'atak']], word_squares(['baba','atak','abat','delt','quad']))
8+
9+
def test_words_squares_multiple_results(self):
10+
self.assertEqual([['will', 'idle', 'lliw', 'lewd'], ['will', 'idle', 'llow', 'lewd']], word_squares(['will','idle','lliw','lewd','llow']))
11+
12+
def test_no_results(self):
13+
self.assertEqual([], word_squares(['baba','free','quad','high','jill']))

0 commit comments

Comments
 (0)