用 Linux 命令行解決 Wordle 問題
我最近有點迷戀上了一個在線單詞猜謎遊戲,在這個遊戲中,你有六次機會來猜一個隨機的五個字母的單詞。這個詞每天都在變化,而且你每天只能玩一次。每次猜測後,你猜測中的每個字母都會被高亮顯示:灰色表示該字母沒有出現在神秘單詞中,黃色表示該字母出現在單詞中,但不在那個位置,綠色表示該字母出現在單詞中的那個正確位置。
下面是你如何使用 Linux 命令行來幫助你玩像 Wordle 這樣的猜測遊戲。我用這個方法來幫助我解決 1 月 6 日的謎題:
第一次嘗試
Linux 系統在 /usr/share/dict/words
文件中保存了一個單詞詞典。這是一個很長的純文本文件。我的系統的單詞文件里有超過 479,800 個條目。該文件既包含純文本,也包含專有名詞(名字、地點等等)。
為了開始我的第一次猜測,我只想得到一個長度正好是五個字母的純文本詞的列表。要做到這一點,我使用這個 grep
命令:
$ grep '^[a-z][a-z][a-z][a-z][a-z]$' /usr/share/dict/words > myguess
grep
命令使用正則表達式來進行搜索。你可以用正則表達式做很多事情,但為了幫助我解決 Wordle 問題,我只需要基本的東西。^
表示一行的開始,$
表示一行的結束。在兩者之間,我指定了五個 [a-z]
的實例,表示從 a 到 z 的任何小寫字母。
我還可以使用 wc
命令來查看我的可能單詞列表,「只有」 15,000 個單詞:
$ wc -l myguess
15034 myguess
從這個列表中,我隨機挑選了一個五個字母的單詞:acres
。a
被設置為黃色,意味著該字母存在於神秘單詞的某處,但不在第一位置。其他字母是灰色的,所以我知道它們並不存在於今天的單詞中。
![acres word attempt](/data/attachment/album/202202/08/121439skac6467c00p4e52.png "acres word attempt")
第二次嘗試
對於我的下一個猜測,我想得到一個包含 a
的所有單詞的列表,但不是在第一位置。我的列表也不應該包括字母 c
、r
、e
或 s
。讓我們把這個問題分解成幾個步驟。
為了得到所有帶 a 的單詞的列表,我使用 fgrep
(固定字元串 grep)命令。fgrep
命令也像 grep
一樣搜索文本,但不使用正則表達式:
$ fgrep a myguess > myguess2
這使我的下一個猜測的可能列表從 15,000 個字下降到 6,600 個字:
$ wc -l myguess myguess2
15034 myguess
6634 myguess2
21668 total
但是這個單詞列表中的第一個位置也有字母 a
,這是我不想要的。遊戲已經表明字母 a
存在於其他位置。我可以用 grep
修改我的命令,以尋找在第一個位置包含其他字母的詞。這就把我可能的猜測縮小到了 5500 個單詞:
$ fgrep a myguess | grep '^[b-z]' > myguess2
$ wc -l myguess myguess2
15034 myguess
5566 myguess2
20600 total
但我知道這個神秘的詞也不包括字母 c
、r
、e
或 s
。我可以使用另一個 grep
命令,在搜索中省略這些字母:
$ fgrep a myguess | grep '^[b-z]' | grep -v '[cres]' > myguess2
$ wc -l myguess myguess2
15034 myguess
1257 myguess2
16291 total
-v
選項意味著反轉搜索,所以 grep
將只返回不符合正則表達式 [cres]
或單列字母 c
、r
、e
或 s
的行。有了這個額外的 grep
命令,我把下一個猜測的範圍大大縮小到只有 1200 個可能的單詞,這些單詞在某處有一個 a
,但不在第一位置,並且不包含 c
、r
、e
、或 s
。
在查看了這個列表後,我決定嘗試一下 balmy
這個詞。
![balmy word attempt](/data/attachment/album/202202/08/121440pluqoifa0peuf80j.png "balmy word attempt")
第三次嘗試
這一次,字母 b
和 a
被高亮顯示為綠色,意味著我把這些字母放在了正確的位置。字母 l
是黃色的,所以這個字母存在於單詞的其他地方,但不是在那個位置。字母 m
和 y
是灰色的,所以我可以從我的下一個猜測中排除這些。
為了確定下一個可能的單詞列表,我可以使用另一組 grep
命令。我知道這個詞以 ba
開頭,所以我可以從這裡開始搜索:
$ grep '^ba' myguess2 > myguess3
$ wc -l myguess3
77 myguess3
這隻有 77 個詞! 我可以進一步縮小範圍,尋找除第三位外還包含字母 l
的詞:
$ grep '^ba[^l]' myguess2 > myguess3
$ wc -l myguess3
61 myguess3
方括弧 [^l]
內的 ^
表示不是這個字母列表,即不是字母 l
。這使我的可能單詞列表達到 61 個,並非所有的單詞都包含字母 l
,我可以用另一個 grep
搜索來消除這些單詞:
$ grep '^ba[^l]' myguess2 | fgrep l > myguess3
$ wc -l myguess3
10 myguess3
這些詞中有些可能包含字母 m
和 y
,而這些字母並不在今天的神秘詞中。我可以再進行一次反轉 grep
搜索,將它們從我的猜測列表中刪除:
$ grep '^ba[^l]' myguess2 | fgrep l | grep -v '[my]' > myguess3
$ wc -l myguess3
7 myguess3
我的可能的單詞列表現在非常短,只有七個單詞!
$ cat myguess3
babul
bailo
bakal
bakli
banal
bauld
baulk
我選擇 banal
作為我下一次猜測的可能的詞,而這恰好是正確的。
![banal word attempt](/data/attachment/album/202202/08/121440u3qadwak7q7h5aca.png "banal word attempt")
正則表達式的力量
Linux 的命令行提供了強大的工具來幫助你完成實際工作。grep
和 fgrep
命令在掃描單詞列表方面提供了極大的靈活性。對於一個基於單詞的猜測遊戲,grep
幫助識別了一個包含 15000 個可能的單詞的列表。在猜測並知道哪些字母出現在神秘的單詞中,哪些沒有,grep
和 fgrep
幫助將選項縮小到 1200 個單詞,然後只剩下 7 個單詞。這就是命令行的力量。
via: https://opensource.com/article/22/1/word-game-linux-command-line
作者:Jim Hall 選題:lujun9972 譯者:geekpi 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive