forked from tiyd-python-2015-05/mystery-word
-
Notifications
You must be signed in to change notification settings - Fork 0
/
demon.py
130 lines (95 loc) · 3.26 KB
/
demon.py
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
import re
import random
def demonize(families, guesses):
"""
picks whether or not a
guess will be correct
based on number of guesses wrong
and current word families
"""
if len(guesses) == 8:
fam = [(key, value) for key, value in families.items()
if not contains(key, guesses)]
if fam:
return max(fam, key=lambda x: len(x[1]))
return random.choice([(key, value) for key, value in families.items()
if contains(key, guesses)])
else:
rand_key = random.choice(list(families.keys()))
key_list = [keys for keys in families.keys()]
key_list = sorted(key_list, key=lambda x: len(pull_indices(x, '_')),
reverse=True)
length = max([len(key_list) // 2, 1])
key = random.choice(key_list[:length])
key = random.choice([key, rand_key])
return key, families[key]
def check_families(guesses, word_list, word):
"""
filters word_list and sorts into families
then evaluates which family is best
and returns the matching new word and the
corresponding word family
"""
families = {}
guess = guesses[-1]
words = [item for item in word_list if contains(item, [guess]) and
not contains(item, guesses[:-1])]
if words: # if there are any matches with this guess, partition
for item in words:
result = None
indices = pull_indices(item, guess)
search_term = replace(word, indices, guess)
if search_term not in families.keys():
result = filter_list(words, search_term, guess)
families[search_term] = result
new_list = [item for item in word_list if not contains(item, guesses)]
if new_list:
families[word] = new_list
return demonize(families, guesses)
else:
return word, [item for item in word_list
if not contains(item, guesses)]
def contains(item, guesses):
"""
Returns True if item contains any guess from guesses
"""
return_list = []
if guesses:
for letter in guesses:
return_list.extend(re.findall(r'{}'.format(letter), item))
return return_list != []
def pull_indices(word, letter):
"""
finds letter if in word
and returns their indices as
a list
"""
return [index for index,let in enumerate(word) if let == letter]
def replace(word, indices, letter):
"""
replaces the letters in the word
at the index specified
with the given letter
"""
if indices:
return_word = ''
for index, this_letter in enumerate(word):
if index in indices:
return_word += letter
else:
return_word += this_letter
word = return_word
return word
def filter_list(word_list, word, repl=None):
"""
takes word and finds
all matching words in word_list
with [^{repl}] subbed
for the '_' entries where needed
"""
if repl is not None:
repl = '[^{}]'.format(repl)
repl_index = pull_indices(word, '_')
word = replace(word, repl_index, repl)
return [entry for entry in word_list if
re.match(r'{}'.format(word), entry)]