-
Notifications
You must be signed in to change notification settings - Fork 0
/
solver.py
169 lines (116 loc) · 4.25 KB
/
solver.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
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
161
162
163
164
165
166
167
168
169
from collections import Counter
import random
solutions = open("solutions.txt", "r")
helpers = open("helpers.txt", "r")
#counts = open("extension/words/word_counts.txt", "r")
allSolutions = solutions.read().split("\n")
allHelpers = helpers.read().split("\n")
allHelpers = list(filter(lambda x: allHelpers.index(x) % 10 == 0, allHelpers))
#freqCounts = counts.read().split("\n")
solutions.close()
helpers.close()
#counts.close()
class Dict(dict):
def __missing__(self, key):
return 0
def getGuess(validSolutions, validHelpers):
allCounts = {}
for i in range(len(validSolutions[0])):
allCounts[i] = Dict()
counter = Counter([w[i] for w in validSolutions])
for gram, count in counter.items():
allCounts[i][gram] = count
maxScore = 0
bestWord = validSolutions[0]
for candidate in validSolutions:
score = 0
for i in range(len(candidate)):
score += allCounts[i][candidate[i]]
if score > maxScore:
maxScore = score
bestWord = candidate
return bestWord
def getGuessDynamically(validSolutions, validHelpers):
if len(validSolutions) == len(allSolutions):
return "soare"
maxScore = 0
bestWord = validSolutions[0]
for candidate in validSolutions + validHelpers:
score = 0
for other in validSolutions:
score += markGuess(other, candidate)[1]
if score > maxScore:
maxScore = score
bestWord = candidate
print(bestWord, score)
return bestWord
def getGuessFrequency(validSolutions, validHelpers):
maxScore = 0
bestWord = validSolutions[0]
for candidate in validSolutions:
score = 0
for count in freqCounts:
count = count.split(" ")
if count[0] in candidate:
score += int(count[1])
if score > maxScore:
maxScore = score
bestWord = candidate
return bestWord
def getGuessRandom(validSolutions, validHelpers):
return random.choice(validSolutions)
def markGuess(answer, guess):
res = [list(t) for t in zip(answer, guess, "NNNNN")]
score = 0
for r in res:
if r[0] == r[1]:
r[2] = "C"
score += 5
for r in res:
if r[2] != "C" and r[1] in answer and answer.count(r[1]) > sum([1 if n != "N" and g == r[1] else 0 for _, g, n in res ]):
r[2] = "P"
score += 2
return res, score
def pruneSearchSpace(res, validSolutions, validHelpers):
counts = Dict()
potentialNots = []
i = 0
for _, g, r in res:
if r == "C":
validSolutions = list(filter(lambda sol: sol[i] == g, validSolutions))
validHelpers = list(filter(lambda sol: sol[i] == g, validHelpers))
else:
validSolutions = list(filter(lambda sol: sol[i] != g, validSolutions))
validHelpers = list(filter(lambda sol: sol[i] != g, validHelpers))
if r != "N":
counts[g] += 1
else:
potentialNots += [g]
i += 1
for letter, count in counts.items():
validSolutions = list(filter(lambda sol: sol.count(letter) >= count, validSolutions))
validHelpers = list(filter(lambda sol: sol.count(letter) >= count, validHelpers))
for pot in potentialNots:
if pot not in counts:
validSolutions = list(filter(lambda sol: pot not in sol, validSolutions))
validHelpers = list(filter(lambda sol: pot not in sol, validHelpers))
print(len(validSolutions), len(validHelpers))
return validSolutions, validHelpers
def solveFor(answer):
validSolutions = list(allSolutions)
validHelpers = list(allHelpers)
tries = 0
res = []
while len(res) == 0 or not all(r == "C" for _, _, r in res):
guess = getGuess(validSolutions, validHelpers)
res, _ = markGuess(answer, guess)
validSolutions, validHelpers = pruneSearchSpace(res, validSolutions, validHelpers)
tries += 1
print(answer, tries)
return tries
def scoreAlg():
scores = []
for word in allSolutions:
scores.append(solveFor(word))
print("avg: %.2f, min: %.2f, max: %.2f" % (sum(scores) / len(scores), min(scores), max(scores)))
scoreAlg()