-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanagrams.py
More file actions
161 lines (125 loc) · 4.85 KB
/
anagrams.py
File metadata and controls
161 lines (125 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""Module for multi-word anagram construction using Counter-based multiset logic."""
from collections import Counter
from itertools import permutations
FORBIDDEN_DIGRAMS = {"vl", "kg", "oq", "mv", "tm", "lr", "md"}
def is_pronounceable(word: str) -> bool:
"""Return True if the word contains no forbidden digrams."""
for i in FORBIDDEN_DIGRAMS:
if i in word:
return False
return True
def has_vc_pattern(word: str) -> bool:
"""Return True if the word follows plausible English V-C patterns."""
vowels = "aeiouy"
consonant_count = 0
for c in word:
if c not in vowels:
consonant_count += 1
else:
consonant_count = 0
if consonant_count >= 4:
return False
return True
def generate_remaining(letters: Counter) -> set:
"""Generate filtered permutations of the remaining letters."""
letters = list(letters.elements())
results = set()
for pr in permutations(letters):
pr = "".join(pr)
if is_pronounceable(pr) and has_vc_pattern(pr):
results.add(pr)
return results
def load_file(file_name: str) -> list:
"""
Load a text file and return a list of lowercase, stripped strings.
Args:
file_name (str): The path to the dictionary file.
Returns:
list: A list of words from the file.
"""
with open(file_name, "r", encoding="utf-8") as file:
content = file.read().split("\n")
content = [x.lower().strip() for x in content]
return content
def find_word_anagrams(word: str, dict_path: str) -> list:
"""Return a list of words from a word that can be built from bank letters."""
content = set(load_file(dict_path))
content = {c.lower() for c in content}
word = word.lower()
w_carcters = sorted(word)
anagrams = []
for w in content:
if len(w) == len(word) and w != word:
if sorted(w) == w_carcters:
anagrams.append(w)
return anagrams
def find_sub_word_anagrams(bank: Counter, dictionary_set: set, name: str) -> list:
"""Return a list of words from dictionary_set."""
anagrams = []
total_letters_left = sum(bank.values())
name = name.lower()
name = name.split()
for w in dictionary_set:
if len(w) <= total_letters_left and w not in name:
if Counter(w) <= bank:
anagrams.append(w)
return anagrams
def view_by_letter(options: list, letter: str) -> list:
"""Filter words starting with a letter."""
filtered = []
for w in options:
if w.startswith(letter):
filtered.append(w)
return filtered
def find_anagram_phrase(dict_path: str) -> str:
"""Build an anagram phrase by depleting a letter bank."""
name = input("Type your name: ")
dictionary_set = {w.lower().strip() for w in load_file(dict_path) if w.strip()}
bank_words = Counter(name.lower().replace(" ", ""))
result = []
options = None
while bank_words:
if options is None:
options = find_sub_word_anagrams(bank_words, dictionary_set, name)
if not options:
print(
f"\nStuck! Remaining: {''.join(sorted(bank_words.elements())).upper()}"
)
choice = input("Type 'permute' to brute-force or 'quit': ").strip().lower()
if choice == "permute":
options = list(generate_remaining(bank_words))
if not options:
print("No pronounceable combinations found.")
break
continue
break
print(f"\nRemaining letters: {' '.join(sorted(bank_words.elements())).upper()}")
print(f"Choices: {options}")
want_filter = input("Filter by starting letter? (y/n): ").lower().strip()
if want_filter == "y":
letter = input("Type letter: ").lower().strip()
if letter.isalpha():
print(f"Filtered Choices: {view_by_letter(options, letter)}")
new_word = input("Type a word, 'permute', or 'quit': ").strip().lower()
if new_word == "quit":
break
if new_word == "permute":
generated = list(generate_remaining(bank_words))
options = list(set(options + generated))
continue
if new_word in options:
result.append(new_word)
bank_words -= Counter(new_word)
options = None
print(f"Added '{new_word}'. Current phrase: {' '.join(result)}")
else:
print(f"Invalid choice! '{new_word}' is not available.")
return " ".join(result)
if __name__ == "__main__":
DICTIONARY_PATH = "dict.txt"
final_phrase = find_anagram_phrase(DICTIONARY_PATH)
if final_phrase:
print("\nFinal Anagram Phrase:")
print(final_phrase.upper())
else:
print("\nExited without completing the anagram.")