# Wordle Solver

github.com/bakert/wordle

``````import random
import sys

MAX_GUESSES = 6
WORD_LENGTH = 5

class Game:
def __init__(self):
self.guesses = []

def guess(self, word):
print('Guessing ' + word)
self.guesses.append(word)
return word == self.word

def incomplete(self):
return len(self.guesses) < MAX_GUESSES

def win(self):
print('You won, the word was ' + self.word)

def lose(self):
print('You lost, the word was ' + self.word)

def num_guesses(self):
return len(self.guesses)

def fixed_letter(self, n):
for g in self.guesses:
if self.word[n] == g[n]:
return self.word[n]
return None

def wild_letters(self):
ls = []
for g in self.guesses:
for l in g:
if l in self.word:
ls.append(l)
return ls

ls = []
for g in self.guesses:
for l in g:
if l not in self.word:
ls.append(l)
return ls

def play():
game = Game()
dictionary = get_dictionary()
game.word = random.choice(dictionary)
while game.incomplete():
if game.num_guesses() == MAX_GUESSES - 1:
else:
best_words = find_best_words(hist, dictionary)
guess = random.choice(best_words)
if game.guess(guess):
game.win()
return
game.lose()

def histogram(words):
hist = {}
for word in words:
for letter in word:
hist[letter] = hist.get(letter, 0) + 1
return hist

r = []
for word in dictionary:
if not has_fixed_letters(word, game):
continue
if not has_wild_letters(word, game):
continue
continue
r.append(word)
return r

def has_fixed_letters(word, game):
for n in range(0, len(word)):
if game.fixed_letter(n) and not word[n] == game.fixed_letter(n):
return False
return True

def has_wild_letters(word, game):
for letter in game.wild_letters():
if letter not in word: # it also can't be in the position(s) guessed incorrectly but we ignore that here
return False
return True

for letter in word:
return True
return False

def find_best_words(hist, dictionary):
r = []
best_score = find_best_score(hist, dictionary)
for word in dictionary:
if score(hist, word) == best_score:
r.append(word)
return r

def find_best_score(hist, dictionary):
best_score = 0
for word in dictionary:
best_score = max(best_score, score(hist, word))
return best_score

def score(hist, word):
found = []
n = 0
for letter in word:
if letter not in found:
n += hist.get(letter, 0)
found.append(letter)
return n

def get_dictionary():
with open('/usr/share/dict/words') as f:
return [w.strip() for w in f.readlines() if len(w.strip()) == WORD_LENGTH and w.lower() == w]

def test():
test_find_best_words()
test_find_best_score()
test_score()
test_get_dictionary()

def test_find_best_words():
hist = {
'a': 10,
'b': 1,
}
dictionary = ['a', 'baa', 'count']
assert find_best_words(hist, dictionary) == ['baa']

def test_find_best_score():
hist = {
'a': 10,
'b': 1,
}
dictionary = ['a', 'baa', 'count']
assert find_best_score(hist, dictionary) == 11

def test_score():
hist = {
'a': 10,
'b': 1,
}
assert score(hist, 'baa') == 11
assert score(hist, 'count') == 0
assert score(hist, 'a') == 10

def test_get_dictionary():
d = get_dictionary()
assert len(d) > 1000
for w in d:
assert len(w) == 5
assert w.lower() == w

if len(sys.argv) < 2:
play()
else:
test()
``````