DeWordle Debugging

Published Monday, January 24, 2022 by Bryan

Remember when I said, "This [Wordle-solving] method is the epitome of 'garbage in, garbage out"? It seems that it fell to "garbage in" yesterday. Some of the tweets I picked up are not correct for Wordle 219.

Answer = [
                  3#00210, 3#00201, 3#22200,         % @omermeroz
                  3#01020, 3#10002,                  % @beckytopia
                  3#01210, 3#02200,                  % @shreyaghoshal
                  3#00100, 3#01201, 3#10210,         % @doriancraycray
                  3#00010, 3#01120,                  % @JakyNinjakitty
                  3#01211,                           % @anniedundun
                  3#01022,                           % @SoWhoIsAmber
                  3#01001, 3#01110, 3#21210,         % @MR0808
                  3#00200, 3#00222,                  % @fitztiptoes
                  3#01010, 3#20110, 3#21000,         % @vibinjabakar
                  3#22000,                           % @nonaness_
                  3#22002,                           % @Turbidarrow212
                  3#02202,                           % @jackomarto
                  3#11020,                           % @kuppanoodle
                  3#00220,                           % @JordanRasko
                  3#10012, 3#10110,                  % @snackynicky
                  3#00121,                           % @zalmaaaa
                  3#02010,                           % @PulloutMethyd
                  3#00211,                           % @taomeslibrary
                  3#01200, 3#11002,                  % @wildestays
                  3#00022, 3#22022,                  % @yasharmouta
                  3#10010, 3#11110,                  % @kdiizzles
                  3#22010,                           % @uwuttaker
                  3#02020,                           % @countjazula
                  3#00002, 3#01002, 3#00101, 3#02022,% @fisforfavorites
                  3#12000, 3#20102, 3#20012,         % @fel_clt
                  3#21021, 3#21011,                  % @spikeymikeyYT
                  3#22112                            % @echipir_
              ].
AnswerSet = ordsets:from_list(Answer).
KnollSet = ordsets:from_list(dewordle:scores_containing_word("KNOLL", Map)).
[dewordle:format_score(S) || S <- ordsets:subtract(AnswerSet, KnollSet)].

🟨🟨🟨🟨⬜
🟩⬜🟨⬜🟩
🟩🟨⬜🟨🟨
🟩🟨⬜🟩🟨
🟩🟩⬜🟨⬜
🟩🟩🟨🟨🟩

The real answer to Wordle 219 is KNOLL. Subtracting its fingerprint (the KnollSet, which I swear is an unintended pun) from the fingerprint I built yesterday (AnswerSet) reveals six patterns that people tweeted as Wordle 219 game summaries that KNOLL can never generate.

grep -e "[NOL][KOL][KNL][KNO][^KNOL]" possible.txt impossible.txt
impossible.txt:LOLOG
impossible.txt:NOLOS
impossible.txt:NONNY
dewordle:format_score(dewordle:score_guess("LOLOG", "KNOLL")).
dewordle:format_score(dewordle:score_guess("NOLOS", "KNOLL")).
dewordle:format_score(dewordle:score_guess("NONNY", "KNOLL")).

🟨🟨🟨⬜⬜
🟨🟨🟨⬜⬜
🟨🟨⬜⬜⬜

Take the first invalid pattern, 🟨🟨🟨🟨⬜. LOLOG, NOLOS, and NONNY are the only words that come close to that score. But none of those gets four yellows, because only the first O or N gets counted correct, but misplaced.

Wordle confirms LOLOG, NOLOS, and NONNY generate at most three yellows
grep -ce "K[^KNOL][KNL][^KNOL]L" possible.txt impossible.txt
possible.txt:0
impossible.txt:0
grep -ce "K[KOL][^KNOL][KNO][KNO]" possible.txt impossible.txt 
possible.txt:0
impossible.txt:0
grep -ce "K[KOL][^KNOL]L[KNO]" possible.txt impossible.txt 
possible.txt:0
impossible.txt:0
grep -ce "KN[^KNOL][KNO][^KNOL]" possible.txt impossible.txt 
possible.txt:0
impossible.txt:0
grep -ce "KN[KNL][KNO]L" possible.txt impossible.txt 
possible.txt:0
impossible.txt:0

None of the other patterns even comes close. So, it seems we need to discard the tweets from @kdiizzles, @fel_clt, @spikeymikeyYT, @uwuttake, and @echipir_. Interestingly, I found all of these after I switched from adding whatever patterns I could find by searching for just "Wordle 219", to searching for specific patterns I expected to reduce the answer space.

ResetWords = dewordle:words_for_scores([
                  3#00210, 3#00201, 3#22200,         % @omermeroz
                  3#01020, 3#10002,                  % @beckytopia
                  3#01210, 3#02200,                  % @shreyaghoshal
                  3#00100, 3#01201, 3#10210,         % @doriancraycray
                  3#00010, 3#01120,                  % @JakyNinjakitty
                  3#01211,                           % @anniedundun
                  3#01022,                           % @SoWhoIsAmber
                  3#01001, 3#01110, 3#21210,         % @MR0808
                  3#00200, 3#00222,                  % @fitztiptoes
                  3#01010, 3#20110, 3#21000,         % @vibinjabakar
                  3#22000,                           % @nonaness_
                  3#22002,                           % @Turbidarrow212
                  3#02202,                           % @jackomarto
                  3#11020,                           % @kuppanoodle
                  3#00220,                           % @JordanRasko
                  3#10012, 3#10110,                  % @snackynicky
                  3#00121,                           % @zalmaaaa
                  3#02010,                           % @PulloutMethyd
                  3#00211,                           % @taomeslibrary
                  3#01200, 3#11002,                  % @wildestays
                  3#00022, 3#22022,                  % @yasharmouta
                  3#02020,                           % @countjazula
                  3#00002, 3#01002, 3#00101, 3#02022 % @fisforfavorites
              ], Map).
true = lists:member("KNOLL", ResetWords).
56 = length(ResetWords).

Removing the invalid patterns does bring KNOLL back into play, but also broadens our answer space to 56. Can we can whittle it back down again? Thanks, @cielavenir (despite the spoiler), @nateroundy, @AmyKatherine_x, @andeaxchiasson, @wowiexist, @sarahfinIey, @hazcraig16, @willlseymour, and @kmatthemovies.

f(ResetWords).
ResetWords = dewordle:words_for_scores([
                  3#00210, 3#00201, 3#22200,         % @omermeroz
                  3#01020, 3#10002,                  % @beckytopia
                  3#01210, 3#02200,                  % @shreyaghoshal
                  3#00100, 3#01201, 3#10210,         % @doriancraycray
                  3#00010, 3#01120,                  % @JakyNinjakitty
                  3#01211,                           % @anniedundun
                  3#01022,                           % @SoWhoIsAmber
                  3#01001, 3#01110, 3#21210,         % @MR0808
                  3#00200, 3#00222,                  % @fitztiptoes
                  3#01010, 3#20110, 3#21000,         % @vibinjabakar
                  3#22000,                           % @nonaness_
                  3#22002,                           % @Turbidarrow212
                  3#02202,                           % @jackomarto
                  3#11020,                           % @kuppanoodle
                  3#00220,                           % @JordanRasko
                  3#10012, 3#10110,                  % @snackynicky
                  3#00121,                           % @zalmaaaa
                  3#02010,                           % @PulloutMethyd
                  3#00211,                           % @taomeslibrary
                  3#01200, 3#11002,                  % @wildestays
                  3#00022, 3#22022,                  % @yasharmouta
                  3#02020,                           % @countjazula
                  3#00002, 3#01002, 3#00101, 3#02022,% @fisforfavorites
                  3#12020, 3#10020, 3#00020,         % @cielavenier
                  3#00102, 3#02012,                  % @nateroundy
                  3#02120, 3#02021, 3#22020,         % @AmyKatherine_x
                  3#11010, 3#20120,                  % @andreaxchiasson
                  3#20022,                           % @wowiexist
                  3#01202,                           % @sarahfinIey
                  3#21200,                           % @hazcraig16
                  3#21020,                           % @willlseymour
                  3#01220                            % @katthemovies
              ], Map).
true = lists:member("KNOLL", ResetWords).
2 = length(ResetWords).

I am all the way down to two words: KNOLL and PINEY. If I could find 🟨🟨🟨🟩⬜, I would be able to cross out PINEY. As it is, I had to switch to searching for Dark Theme squares, 🟨🟨🟨🟩⬛ to get the last few. I tried the color-blind setting's 🟦🟦🟦🟧⬛ and 🟦🟦🟦🟧⬜ as well, with no further luck.

grep -e "[NOL][KOL][KNL]L[^KNOL]" possible.txt impossible.txt 
impossible.txt:LOLLS
impossible.txt:LOLLY
impossible.txt:NOLLS
dewordle:format_score(dewordle:score_guess("LOLLS", "KNOLL")).
dewordle:format_score(dewordle:score_guess("LOLLY", "KNOLL")).
dewordle:format_score(dewordle:score_guess("NOLLS", "KNOLL")).

🟨🟨⬜🟩⬜
🟨🟨⬜🟩⬜
🟨🟨🟨🟩⬜

Wordle confirms tha NOLLS is our missing guess.

NOLLS. Okay. I understand now why no one has guessed the 🟨🟨🟨🟩⬜ word.

PineySet = ordsets:from_list(dewordle:scores_containing_word("PINEY", Map)).
[dewordle:format_score(S) || S <- ordsets:subtract(KnollSet, PineySet)].

🟨🟨🟨🟩⬜

So it was always meant to be this way. The only pattern that a KNOLL guess can produce that a PINEY guess can't is 🟨🟨🟨🟩⬜.

43 = length(ordsets:subtract(PineySet, KnollSet)).

Interestingly, the reverse is not true. PINEY guesses can generate 43 patterns that KNOLL can't. I said yesterday that we couldn't rule out a word based only on being unable to find any tweets showing someone seeing at least one of its patterns. But if none of forty-three patterns are found, we could be pretty sure.

% The patterns that SPIEL used yesterday, that KNOLL does not
BadSet = ordsets:subtract(AnswerSet, KnollSet).
[dewordle:format_score(S) || S <- ordsets:intersection(BadSet, ordsets:subtract(PineySet, KnollSet))].

🟨🟨🟨🟨⬜
🟩⬜🟨⬜🟩
🟩🟨⬜🟨🟨
🟩🟩⬜🟨⬜

Unfortunately, without even going to Twitter, I know we'll find some of these patterns. In fact, four PINEY patterns were part of what threw off yesterday's attempt. It's tempting to use some heuristic like, "Multiple people must tweet a pattern before we consider it valid." But, some of the patterns used to get us all the way to just KNOLL and PINEY are one-tweet-only.

So, while the theory holds that you can solve Wordle only using these diagrams, without knowing any letters guessed, the practice does not. If you only use diagrams from people you trust to post accurate ones, you can narrow your search down quite a bit. Combining this reduction with one of the many other ways to pick a good starting word might even improve your guess count. But, it seems that using this method, relying only on the accuracy of strangers, is not effective.

I'm leaving the code up on github (beerriot/dewordle), because it has been a lot of fun to play with. Let me know if you find improvements to make. Thanks for reading!

Categories: Development