Refactor dictionary logic into it's own file.

This commit is contained in:
dongar committed 2023-05-23 12:04:31 -05:00
1 parent b3b9601abc
commit 497c48f853
2 files changed
+90 -85

No files matched your search

+10 -85
View File
@@ -6,7 +6,7 @@ import string
from enum import Enum
from collections import defaultdict
WORDLE_LENGTH = 5
import dictionary
class LetterResult(Enum):
@@ -24,92 +24,17 @@ class InvalidWord(Exception):
pass
_wordle_dictionary = set()
_invalid_words = set(
[
"amala",
"arara",
"araru",
"araua",
"arawa",
"balak",
"batak",
"bayal",
"beala",
"beata",
"beele",
"boily",
"bolty",
"bruke",
"carlo",
"caroa",
"carot",
"carum",
"divet",
"doray",
"erept",
"fikie",
"genae",
"ghole",
"gotra",
"hirse",
"hyrse",
"katat",
"korah",
"macco",
"mitra",
"muang",
"nurry",
"odell",
"odell",
"petro",
"pindy",
"quito",
"retan",
"roter",
"sisel",
"skeel",
"staia",
"stail",
"sussy",
"tebet",
"telae",
"theet",
"undig",
"uninn",
"unkin",
"vedet",
"whalm",
"whaly",
]
)
def dictionary():
if not _wordle_dictionary:
with open("words_alpha.txt") as word_file:
all_words = word_file.read().split()
_wordle_dictionary.update(
filter(
lambda w: len(w) == WORDLE_LENGTH and w not in _invalid_words, all_words
)
)
return _wordle_dictionary
def select_word():
return random.choice(list(dictionary()))
return random.choice(list(dictionary.words()))
def grade_word(target, guess):
# We don't check word length, since all valid words are 5 letters.
if guess not in dictionary():
if guess not in dictionary.words():
raise InvalidWord(f"{guess} is not a valid Wordle.")
result = [LetterResult.UNKNOWN] * WORDLE_LENGTH
result = [LetterResult.UNKNOWN] * dictionary.WORDLE_LENGTH
# We copy target, and remove letters if we find them. This handles duplicate letters correctly.
# For example, if the target is "pulls" and we guess "apple", only the first "p" should be a
@@ -117,12 +42,12 @@ def grade_word(target, guess):
remaining = list(target)
# Find all correct results first.
for i in range(WORDLE_LENGTH):
for i in range(dictionary.WORDLE_LENGTH):
if target[i] == guess[i]:
result[i] = LetterResult.CORRECT
remaining.remove(guess[i])
for i in range(WORDLE_LENGTH):
for i in range(dictionary.WORDLE_LENGTH):
if result[i] == LetterResult.UNKNOWN:
if guess[i] in remaining:
# Letter is in the wrong place.
@@ -198,7 +123,7 @@ def score_word(position_matches, word_matches, word):
return result
def scored_words(wordle_dictionary=dictionary()):
def scored_words(wordle_dictionary=dictionary.words()):
# word: score
scored_words = dict()
@@ -216,9 +141,9 @@ def scored_words(wordle_dictionary=dictionary()):
class Constraints:
def __init__(self):
# Array of known letters in result with None for unknown.
self.correct = [None] * WORDLE_LENGTH
self.correct = [None] * dictionary.WORDLE_LENGTH
# Array with per-letter sets of known bad letters.
self.incorrect = [set() for _ in range(WORDLE_LENGTH)]
self.incorrect = [set() for _ in range(dictionary.WORDLE_LENGTH)]
# Dict of letter -> int with minimum required count of letter in word.
self.count = defaultdict(int)
# If letter is present in set, value in min is both min and max.
@@ -272,7 +197,7 @@ class Constraints:
return True
def filter_dictionary(constraints, wordle_dictionary=dictionary()):
def filter_dictionary(constraints, wordle_dictionary=dictionary.words()):
return set(filter(lambda w: constraints.matches(w), wordle_dictionary))