-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
167 lines (103 loc) · 4.67 KB
/
bot.py
File metadata and controls
167 lines (103 loc) · 4.67 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
161
162
163
164
165
166
from itertools import product
from wordle import Wordle, LetterState, WordleFullException, ANSI_RESET, load_word_list
import logger
logger = logger.Logger(True,
False,
"$color[$info]$reset $timecolor[%H:%M:%S.%f]$reset $message $tracecolor($filename/$funcname:$line)$reset")
logger.reset_log()
FIRST = 'trace'
class WordleBot:
def __init__(self):
self.valid_guess_words = load_word_list('valid-wordle-list.txt')
self.over_words = load_word_list('todays-wordle-candidate.txt')
def solve(self, wordle: Wordle):
print(list(product([LetterState.NONE, LetterState.INCLUDE, LetterState.CORRECT], repeat=5)))
# valid_words = self.valid_words
over_words = self.over_words
valid_guess_words = self.valid_guess_words
guesses = [(FIRST, wordle.guess(FIRST))]
logger.log(f'First guess "{FIRST}" done')
try:
while 1:
if guesses[-1][0] in over_words: # remove guessed word from it's possible answer
over_words.remove(guesses[-1][0])
valid_guess_words.remove(guesses[-1][0])
over_words = self.possible_words(over_words, guesses[-1]) # filter possible answer by checking the pattern of the earlier guess
logger.log(f'{len(over_words)} remaining:', over_words)
print()
while len(over_words) <= 2:
wordle.guess(over_words[0])
_best = self.best_word(over_words, valid_guess_words)
# print(_best)
guesses.append((_best, wordle.guess(_best)))
except WordleFullException:
pass
def count_letters(self, letter: str, word, state: list[LetterState]) -> int:
count = 0
for i in range(5):
if word[i] == letter and (state[i] == LetterState.CORRECT or state[i] == LetterState.INCLUDE):
count += 1
return count
def possible_words(self, possible: list[str], _guess: tuple[str, list[LetterState]]) -> list[str]:
out = []
for word in possible:
guess, state = _guess
for i in range(5):
letter = word[i]
s = state[guess.find(letter)]
if letter in guess and s == LetterState.NONE:
break
if state[i] == LetterState.INCLUDE and letter == guess[i]:
break
if state[i] == LetterState.INCLUDE and guess[i] not in word:
break
if state[i] == LetterState.CORRECT and guess[i] is not letter:
break
if self.count_letters(word[i], guess, state) > self.count_letters(word[i], word, [LetterState.CORRECT] * 5):
break
else:
out.append(word)
return out
def best_word(self, over_words: list[str], guess_words: list[str]) -> str:
best = None
best_rate = None
# for new_state in list(product([LetterState.NONE, LetterState.INCLUDE, LetterState.CORRECT], repeat=5)):
# for s in new_state:
# print(s + ' ', end=ANSI_RESET)
# print()
# return
for j, word in enumerate(guess_words):
# print('\r', j, len(guess_words), end='')
_set = {}
for new_state in list(product([LetterState.NONE, LetterState.INCLUDE, LetterState.CORRECT], repeat=5)):
r = self.possible_words(over_words, (word, new_state))
if not r: # if the state is impossible
continue
idx = len(r)
if idx not in _set:
_set[idx] = 0
_set[idx] += 1
if _set == {}: # if the set is impossible (?)
continue
_set = dict(sorted(_set.items()))
if best_rate is None or best is None:
logger.error("Assigning", word, _set, "because best doesnt exist")
if best_rate is None or best is None or self.better2(_set, best_rate):
best_rate = _set
best = word
print(best, best_rate)
logger.log("best is", best_rate, best)
return best
def better2(self, a: dict, b: dict):
if max(a.keys()) <= max(b.keys()):
if max(a.keys()) < max(b.keys()):
return True
else:
return sum(a.values()) > sum(b.values())
return False
if __name__ == '__main__':
# fuzzy
wordle = Wordle("pollo")
bot = WordleBot()
bot.solve(wordle)
# bot.helps_words(wordle._correct, bot.guess_words)