wordle
The {wordle}
package contains code to assist in finding good candidate
words for Wordle.
“Wordle” itself is a guess-a-word puzzle playable online.
The game plays like the old ‘mastermind’ board game, but with letters instead of coloured pins. The gameplay is as follows:
- Enter a word as a guess for the hidden target word.
- Any letters which are within the hidden target word are coloured in yellow.
- Any letters which match exactly the letter in the hidden target word are coloured green
- Figure out a new candidate word as a guess for the hidden target word, and go back to Step 1.
In the following game of Wordle, the first guess was eaten
, the second was
arise
, and then the third guess really only has one good option given the
constraints revealed so far: aside
. This was the hidden target word,
which means the puzzle is solved!
The process of finding good candidate words given letters which have been seen so far is a good match for regular expressions. This package aims to help you find these good candidate words.
What’s in the box
Wordle
R6 Class is the primary way of finding candidate words. It has the following methods:$new()
to start a new object to help with a new puzzle. Use theword_file
argument to set the location of a list of words to start with. This defaults to/usr/share/dict/words
(which should work on macOS and many unix-ish systems).$words
to get a list of candidate words given the words and responses that have been seen so far$update()
to notify the object of what the latestword
was, and the colour responses received back from the game for each letter.
filter_words()
is a stateless function for filtering a list of words by various constraints on letter position.- The
Wordle
class is a stateful wrapper aroundfilter_words()
- The
Installation
You can install from GitHub with:
# install.package('remotes')
remotes::install_github('coolbutuseless/wordle')
Solving a puzzle with Wordle
puzzle <- wordle::WordleHelper$new(nchar = 5)
head(puzzle$words, 20)
#> [1] "aahed" "aalii" "aargh" "aarti" "abaca" "abaci" "aback" "abacs" "abaft"
#> [10] "abaka" "abamp" "aband" "abase" "abash" "abask" "abate" "abaya" "abbas"
#> [19] "abbed" "abbes"
Guess eaten
There are a lot of uncommon words in the word list, and the online puzzle doesn’t
accept some of them, so you’ll need to pick out a likely word - in this case
I picked: eaten
Update puzzle state with the word played and the response:
puzzle$update("eaten", c('yellow', 'grey', 'grey', 'grey', 'grey'))
head(puzzle$words, 20)
#> [1] "bebop" "becks" "bedim" "befog" "begum" "beigy" "belch" "bells" "belly"
#> [10] "below" "bemix" "bemud" "bergs" "berko" "berks" "berms" "berob" "berry"
#> [19] "beryl" "besom"
Guess rodeo
Update puzzle state with the word played and the response:
puzzle$update("rodeo", c('yellow', 'grey', 'grey', 'yellow', 'grey'))
puzzle$words
#> [1] "bergs" "berks" "berms" "berry" "beryl" "biers" "birle" "birse" "breis"
#> [10] "brers" "brews" "breys" "bribe" "brise" "brize" "brule" "brume" "burke"
#> [19] "burse" "cerci" "ceric" "clerk" "crems" "creps" "crepy" "cress" "crews"
#> [28] "crime" "cripe" "crise" "cruse" "cruve" "curie" "curse" "curve" "femur"
#> [37] "ferly" "fermi" "ferms" "ferry" "fibre" "fiers" "fiery" "firie" "fleur"
#> [46] "fresh" "frise" "frize" "furze" "gebur" "germs" "germy" "grews" "greys"
#> [55] "grice" "grike" "grime" "gripe" "grise" "grize" "grufe" "grume" "gryce"
#> [64] "gryke" "grype" "gurge" "heirs" "herbs" "herby" "herls" "herms" "herry"
#> [73] "huers" "icers" "jerks" "jerky" "jerry" "jirre" "kefir" "keirs" "kerbs"
#> [82] "kerfs" "kerky" "kerry" "kiers" "kurre" "kyrie" "lehrs" "leirs" "lemur"
#> [91] "lerps" "liers" "livre" "lucre" "lurve" "merch" "mercs" "mercy" "meril"
#> [100] "meris" "merks" "merls" "merry" "murre" "perch" "percs" "peril" "peris"
#> [109] "perks" "perky" "perms" "perps" "perry" "pervs" "pervy" "piers" "preif"
#> [118] "prems" "premy" "preps" "press" "prexy" "preys" "price" "prime" "prise"
#> [127] "prize" "pryse" "puers" "purge" "purse" "query" "quire" "sehri" "seirs"
#> [136] "serfs" "seric" "serif" "serks" "serrs" "serry" "serum" "shire" "sieur"
#> [145] "skers" "skyre" "smerk" "speir" "sperm" "spire" "sprue" "spyre" "sucre"
#> [154] "suers" "surge" "sweir" "swerf" "swire" "umbre" "ureic" "users" "usure"
#> [163] "verbs" "verry" "vezir" "viers" "virge" "weirs" "wersh" "wreck" "xeric"
#> [172] "xerus" "yerks" "zerks"
Guess shire
Update puzzle state with the word played and the response:
puzzle$update("shire", c('grey', 'grey', 'grey', 'green', 'yellow'))
puzzle$words
#> [1] "berry" "clerk" "ferry" "jerry" "kerry" "merry" "perry" "query" "verry"
Guess merry
Update puzzle state with the word played and the response:
puzzle$update("merry", c('grey', 'green', 'green', 'green', 'green'))
puzzle$words
#> [1] "berry" "ferry" "jerry" "kerry" "perry" "verry"
Guess ferry
Success!
Expert Users: filter_words()
The Wordle
R6 class is just a stateful wrapper around a core function
called filter_words()
.
In general you wouldn’t need to call this function for solving a Wordle puzzle but it might come in handy for other word puzzles.
In this example, I’m searching for a word:
- with 9 letters
- starting with
p
- containing
v
andz
somewhere, but not as the first letter - containing only one
z
- without an
a
or ano
in it
words <- readLines("/usr/share/dict/words")
filter_words(
words = words,
exact = "p........",
wrong_spot = c("vz", "", "", "", "", "", "", "", ""),
min_count = c(v = 1),
known_count = c(z = 1, a = 0, o = 0)
)
#> [1] "pulverize"