I’ve recently finished adding Wordle to my
short list of “word game helper” apps. After playing a couple of times unaided by
a computer, it seemed fun to put together a short algorithmic solution to help
ensure a continued 100% win streak! You can find the source here.
Continue reading for an overview of the approach and an analysis of Big
First a short snippet of the high-level logic:
def suggest(wordle, excluded, included, misplaced):
"""
Client entrypoint for suggesting Wordle solutions.
"""
return score(discard(misplaced, search(wordle, exclude(excluded, include(included, corpus)))))
The intent is to:
- Use a list of all known 5 letter English words (“corpus”)
- Include from the corpus, words that “include” a given set of letters
- Exclude form the corpus, words that “exclude” a given set of letters
- Search this subset of included/excluded words for words matching a “wordle” guess (using “.” for positions whose letter we do not know (shaded gray in Wordle) and the actual letter itself for those correctly positioned (Wordle shaded green))
- Subtracting from the search, words that have letters that we know are “misplaced” (in Wordle these are shaded yellow)
- Finally score the words remaining after performing the above and return in descending score order
Quick definition for variables used in analysis.
exclude(excluded, include(included, corpus))
include
is not necessarily the same exclude
, but is of course
required to be strictly <= the initial include
.
Time complexity for include:
def include(letters, corpus):
"""
Return words in corpus that include all letters in `letters`.
"""
return set(filter(lambda word: set(word) & set(letters) == set(letters), corpus))
A single pass over each word in corpus is done, so this already requires
Similar analysis can be used for exclude
, although our constant size will be slightly larger:
There are 26 letters in the English alphabet so we know that
The search operation follows analogously, as we are again doing a single pass with a constant time check to apply our regular expression, which simplifies to a single pass over our regex and strings, both of which are fixed at 5.
Only when we apply discard
do we get a seemingly quadratic upper bound when we apply the
I hope to have shown that Wordle’s restriction to valid 5 letter words greatly reduces the size of inputs to our functions which can be leveraged to arrive at a tighter bounded linear running time (excluding scoring which has been omitted and will come in a future post since this one is is already a bit lengthy).