今回は最近twitterで話題になっている
Wordleをプログラムで解いてみることにしました。
解説動画はこちら
wordleとは6回の試行の間に
・文字と位置があっていれば緑
1回目はあてずっぽうで何かしらを答えてみて
2回目以降はヒントを元に単語を絞り込んでいきます。
1文字目が緑ならその文字で始まる英単語に絞られるので
相当有利になります。
黄色のヒントでも、それが5つ出れば
その5文字で構成される英単語になるので
おのずと絞り込み出来ます。
ヒントが全くつかない灰色の場合は
その文字が使われない英単語であることが
予測できる訳です。
以上の結果から
英単語をどんどん除外して行き
候補だけを残すようなプログラムを考えました。
google colabで使えるようにしてますので
ここから先のコードを利用したい方は
google colabで動かしてみて下さい。
まず最初にファイルをダウンロードします。
これは英単語のリストになります。
これでgoogle colab上のファイル置き場に
ファイルがダウンロードされます。
場所としては
「/content」配下に置かれます。
このファイルを読み込みしておきましょう。
英単語をリストに読み込みする
次にいろいろな関数群を整備します。
まずは正答と自分の回答があっているかどうかを
判定する関数です。
判定の結果をリストで返します。
0:当たってない
1:文字のみ当たり
2:文字も場所も当たり
解答と答えが合うかを判定する
次に回答の結果から
英単語を絞り込む関数群です。
先ほどの結果で0が出たら除外候補に
1や2が出たら、文字候補にして
該当する英単語を絞って行きます。
候補を絞る関数を作る
さてこれであらかた用意できました。
「happy」という単語を正当として
これを何回で当てられるのかを
シミュレーションしてみましょう。
シミュレーションしてみる
はい結果が出ました。
6回で答えが出せなかったものは
99にしています。
この結果を見ると
80%くらいで6回以内には
答えられるような感じなんだと思います。
最後に英単語を予測する部分を
考えてみましょう。
回答の英単語と、そのヒント結果から
次の候補となる単語を予測するプログラムです。
結果から候補を推測するプログラム
使い方は次のようになっています。
色々出しちゃってますが
・緑色ヒントの文字
・黄色ヒントの文字
・除外文字
・候補単語
という感じで出るので
wordleが解けない方は
うまく活用してみて下さい。
6回あればほぼほぼ
解けるんだという感じなので
中々良い難易度のゲームですよね。
twitterだと

こんな感じの絵が出回ってると思いますが
これがゲームの結果なので
最短手数でゲーム攻略をするには
プログラムの力を借りた方が良いですね。
自力で解けたらすごいと思います。
今回はwordleを解く
プログラムを考えてみました。
それでは。
Wordleをプログラムで解いてみることにしました。
解説動画はこちら
wordleとは6回の試行の間に
5文字の英単語を推測するゲームで
・文字と位置があっていれば緑
・文字のみあっている場合は黄色
のヒントが出されるので
これを参考にして英単語を
当てる感じになります。

wikiの画像を参考にするとのヒントが出されるので
これを参考にして英単語を
当てる感じになります。

1回目はあてずっぽうで何かしらを答えてみて
2回目以降はヒントを元に単語を絞り込んでいきます。
1文字目が緑ならその文字で始まる英単語に絞られるので
相当有利になります。
黄色のヒントでも、それが5つ出れば
その5文字で構成される英単語になるので
おのずと絞り込み出来ます。
ヒントが全くつかない灰色の場合は
その文字が使われない英単語であることが
予測できる訳です。
以上の結果から
英単語をどんどん除外して行き
候補だけを残すようなプログラムを考えました。
google colabで使えるようにしてますので
ここから先のコードを利用したい方は
google colabで動かしてみて下さい。
まず最初にファイルをダウンロードします。
これは英単語のリストになります。
!wget https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english-no-swears.txt
これでgoogle colab上のファイル置き場に
ファイルがダウンロードされます。
場所としては
「/content」配下に置かれます。
このファイルを読み込みしておきましょう。
英単語をリストに読み込みする
import random
import re
word_list = []
with open('/content/google-10000-english-no-swears.txt') as _f:
for row in _f:
txt = row.replace('\n','').replace(' ','')
if len(txt)==5:
word_list.append(txt)
#break
word_list.sort()
print(len(word_list))
次にいろいろな関数群を整備します。
まずは正答と自分の回答があっているかどうかを
判定する関数です。
判定の結果をリストで返します。
0:当たってない
1:文字のみ当たり
2:文字も場所も当たり
解答と答えが合うかを判定する
# 解答と答えを照らし合わせて判定する
# 0:無ヒット , 1:ワードのみヒット , 2:場所もヒット
def check_wordle(w , a):
ch = [0,0,0,0,0]
for i,c in enumerate(w):
if c in a:
ch[i]=1
if c==a[i]:
ch[i]=2
return ch
print(check_wordle('haple','habby'))
[2,2,0,0,0]次に回答の結果から
英単語を絞り込む関数群です。
先ほどの結果で0が出たら除外候補に
1や2が出たら、文字候補にして
該当する英単語を絞って行きます。
候補を絞る関数を作る
# 文字候補リストと除外リストを作る
def make_list(word , ch , res , exc):
res = res | {w for w,c in zip(word , ch) if c>=1}
exc = exc | {w for w,c in zip(word , ch) if c==0}
return res , exc
# 候補かどうかをチェックする
def check_hit(word , ch , content , res , exc):
pattern = ''
for w,c in zip(word , ch):
if c==2:
pattern+=w
else:
pattern+='\w'
match = re.search(pattern, content)
rs , ex = False , True
for r in res:
if r in content:
rs=True
if len(res)==0:
rs=True
for e in exc:
if e in content:
ex=False
if match and rs and ex:
return True
else:
return False
# 候補を絞る
def squeeze(word , ch , word_list , res , exc):
s_list = []
for content in word_list:
if check_hit(word , ch , content , res , exc):
s_list.append(content)
return s_list
さてこれであらかた用意できました。
「happy」という単語を正当として
これを何回で当てられるのかを
シミュレーションしてみましょう。
シミュレーションしてみる
# 施行実験を繰り返す
def trial_answer(answer = 'happy'):
s_list , res , exc = [] , set() , set()
for i in range(6):
if i==0:
word = random.choice(word_list)
ch = check_wordle(word , answer)
if ch ==[2,2,2,2,2]:
return i +1 , word
res , exc = make_list(word , ch , res , exc)
s_list = squeeze(word , ch , word_list , res , exc)
#print(word , ch)
else:
word = random.choice(s_list)
ch = check_wordle(word , answer)
if ch ==[2,2,2,2,2]:
return i +1 , word
res , exc = make_list(word , ch , res , exc)
s_list = squeeze(word , ch , word_list , res , exc)
#print(word , ch)
if i>=5:
return 99 , word
calc_dict = {}
n = 1000
for i in range(n):
answer = random.choice(word_list)
num , word = trial_answer(answer)
if num in calc_dict:
calc_dict[num] +=1
else:
calc_dict[num] =1
for k,v in sorted(calc_dict .items()):
print('{0:02}回 : {1:03} , {2:0.1%}'.format(k , v , v/n))
01回 : 001 , 0.1%
02回 : 022 , 2.2%
03回 : 108 , 10.8%
04回 : 231 , 23.1%
05回 : 260 , 26.0%
06回 : 184 , 18.4%
99回 : 194 , 19.4%
はい結果が出ました。
6回で答えが出せなかったものは
99にしています。
この結果を見ると
80%くらいで6回以内には
答えられるような感じなんだと思います。
最後に英単語を予測する部分を
考えてみましょう。
回答の英単語と、そのヒント結果から
次の候補となる単語を予測するプログラムです。
結果から候補を推測するプログラム
# 文字候補リストと除外リストを作る
def make_list2(word , ch , t2 , res , exc):
for i,(w,c) in enumerate(zip(word , ch)):
if c==2:
t2[i] = w
res = res | {w for w,c in zip(word , ch) if c>=1}
exc = exc | {w for w,c in zip(word , ch) if c==0}
return t2 , res , exc
# 候補かどうかをチェックする
def check_hit2(content , t2 , res , exc):
pattern = ''
for i in range(5):
if i in t2:
pattern += t2[i]
else:
pattern+='\w'
match = re.search(pattern, content)
rs , ex = False , True
for r in res:
if r in content:
rs=True
if len(res)==0:
rs=True
for e in exc:
if e in content:
ex=False
if match and rs and ex:
return True
else:
return False
# 候補を絞る
def squeeze2(word_list , t2 , res , exc):
s_list = []
for content in word_list:
if check_hit2(content , t2 , res , exc):
s_list.append(content)
return s_list
# 結果から候補を推測する
# think_dict = {英単語 : [0,1,2,0,0] , ・・・}
def think_answer(think_dict={}):
s_list , t2 , res , exc = [] , {} , set() , set()
for k,v in think_dict.items():
t2 , res , exc = make_list2(k , v , t2 , res , exc)
s_list = squeeze2(word_list , t2 , res , exc)
return t2 , res , exc , s_list
# happy
d = {'miami': [0, 0, 1, 0, 0], 'paths': [1, 2, 0, 1, 0],'panel': [1, 2, 0, 0, 0],'favor': [0, 2, 0, 0, 0],'daddy': [0, 2, 0, 0, 2]}
#d = {'miami': [0, 0, 1, 0, 0], 'paths': [1, 2, 0, 1, 0],'panel': [1, 2, 0, 0, 0],'favor': [0, 2, 0, 0, 0]}
print(think_answer(d))
({1: 'a', 4: 'y'}
{'y', 'p', 'h', 'a'}
{'n', 'o', 'm', 'd', 'e', 't', 'v', 'i', 'f', 'r', 's', 'l'}
['happy'])
{'y', 'p', 'h', 'a'}
{'n', 'o', 'm', 'd', 'e', 't', 'v', 'i', 'f', 'r', 's', 'l'}
['happy'])
使い方は次のようになっています。
think_answer({英単語 : [ヒントを0,1,2で]})
色々出しちゃってますが
・緑色ヒントの文字
・黄色ヒントの文字
・除外文字
・候補単語
という感じで出るので
wordleが解けない方は
うまく活用してみて下さい。
6回あればほぼほぼ
解けるんだという感じなので
中々良い難易度のゲームですよね。
twitterだと

こんな感じの絵が出回ってると思いますが
これがゲームの結果なので
最短手数でゲーム攻略をするには
プログラムの力を借りた方が良いですね。
自力で解けたらすごいと思います。
今回はwordleを解く
プログラムを考えてみました。
それでは。

コメントする