Pythonを用いてPOKEMON WORDLEを解く

## はじめに
この記事では，Pythonを用いてPOKEMON WORDLEを攻略していきます．
POKEMON WORDLEの解答のネタバレを含みます．ご注意ください．
## POKEMON WORDLEとは
URL:https://wordle.mega-yadoran.jp/
巷で話題のWordleのポケモンバージョンです．[こちらの記事](https://zenn.dev/chuprod/articles/6006664b03bb0f)で作成の経緯が紹介されています．

私は本当はポケモンLEGENDS アルセウスがやりたいのですが，お金がないので無料で遊べるこちらのゲームを楽しませてもらっています．

このゲームには今日の「今日のお題」と「エンドレス」という二つのゲームモードがありますが，この記事では対象を「今日のお題」モードとしています．

今日のお題モードの補足ルール(ゲームサイトより抜粋)

- 今日のお題モードにはダイパまでのポケモンしか出ません
- お題のポケモンは必ず５文字です
- 回答には５文字以下のポケモンも入力することができます
- 回答には剣盾までのポケモンが使えます

## ポケモンのリストを作る
まず，回答のためのポケモンの名前を集めたリストを作っていきます．リストの作成方法は色々あると思いますが，今回は[ポケモンwiki](https://wiki.xn--rckteqa2e.com/wiki/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3%E4%B8%80%E8%A6%A7)をPython&BeautifulSoupを用いてスクレイピングして自動で作成しようと思います．

ブラウザの検証ツールを用いてポケモンの名前の属性を確認すると，aタグでできていることがわかります．そこで，以下のようにして，aタグの要素を集めます．

```py
import urllib.request as req
from bs4 import BeautifulSoup

url="https://wiki.xn--rckteqa2e.com/wiki/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3%E4%B8%80%E8%A6%A7"

response=req.urlopen(url)
parse_html=BeautifulSoup(response,'html.parser')

a_list=parse_html.find_all('a')

for i  in range(len(a_list)):
        print(a_list[i].string)
```
このコードを実行してみると，最初と最後にいらない要素，途中にポケモンのタイプが名前と同時に取得されてることがわかります．

ここは愚直に，最初と最後のいらない要素は手動でfor文の範囲を決めて消去し，ポケモンのタイプのリストを作り，持ってきた要素がそのリストにあれば省くような操作を入れます．また，「ガラルのすがた」のような文字列も取得してしまうので，それは文字列の長さで弾きます(ポケモン名の最大長は6)．

```py
a_list=parse_html.find_all('a')
non_pokemon_list=['ノーマル','ほのお','みず','でんき','くさ','こおり','かくとう',
'どく','じめん','ひこう','エスパー','むし','いわ','ゴースト','ドラゴン','あく','はがね','フェアリー']
for i  in range(11,len(a_list)-75):
    if (a_list[i].string not in non_pokemon_list and len(a_list[i].string)<=6):
        print(a_list[i].string)
```

今回は得られた結果をprintする代わりにpokemonlistfile.txtに1行ずつ書き込んでいきます．また，同一の名前がいくつか取得されてしまうので，9行目でそれを一つに統合しています．最終的なコードは以下です．

```py
import urllib.request as req
from bs4 import BeautifulSoup

url="https://wiki.xn--rckteqa2e.com/wiki/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3%E4%B8%80%E8%A6%A7"

response=req.urlopen(url)
parse_html=BeautifulSoup(response,'html.parser')
a_list=parse_html.find_all('a')
list=list(dict.fromkeys(a_list))
non_pokemon_list=['ノーマル','ほのお','みず','でんき','くさ','こおり','かくとう',
'どく','じめん','ひこう','エスパー','むし','いわ','ゴースト','ドラゴン','あく','はがね','フェアリー']

f = open('pokemonlistfile.txt', 'w')

for i  in range(11,len(list)-75):
    if (list[i].string not in non_pokemon_list and len(list[i].string)<=6):
         f.write(list[i].string+'\n')
f.close()

```

こうして得られたpokemonlistfile.txtをみてみると，「ゴミのミノ」などの不要な文字列があったり，ポケモン名の「ゴースト」がタイプのリストに入っているために消えていたりするので，そこは自分の手で修正します．
## ポケモン名を解析する
ポケモン名のリストを作成したら，それを用いて文字頻度表を作成します．先ほど作成したテキストファイルを開き，count()を使って全てのカタカナに対して出現回数をカウントしていきます．

```py
f = open('pokemonlistfile.txt', 'r')
data=f.read()
f.close()
katakana = [chr(i) for i in range(ord('ァ'), ord('ヺ')+1)]
count_list=[]
for i in katakana:
    print(i+':'+str(data.count(i)))
    count_list.append(data.count(i))
```
また，得られたデータをmatplotlibライブラリを用いて棒グラフに可視化し，その後降順(=出現頻度が多い順)に出力します．最終的なコードは以下です．japanize_matplotlibというのは，表にカタカナを文字化けせずに出力するために用いているライブラリです．

```py
import matplotlib.pyplot as plt
import japanize_matplotlib
f = open('pokemonlistfile.txt', 'r')
data=f.read()
f.close()
katakana = [chr(i) for i in range(ord('ァ'), ord('ヺ')+1)]
count_list=[]
for i in katakana:
    print(i+':'+str(data.count(i)))
    count_list.append(data.count(i))
plt.bar(katakana,count_list)
plt.title('ポケモン名の文字出現頻度')
plt.show()
dict_katakana=dict(zip(katakana,count_list))
sorted_katakana=sorted(dict_katakana.items(),key=lambda x:x[1],reverse=True)
print(sorted_katakana)
```
このコードを実行すると，以下のような棒グラフが得られました．横軸は各文字を表していて，縦軸は文字の出現回数を表しています．一番よく出てくる文字は「ー」で，次は「ン」「ラ」「ル」「ス」...のようになりました．
![スクリーンショット 2022-01-31 23.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510592/506e13d2-15a2-f9c5-063f-96287555977f.png)


## Wordleを解く
ここまでで得られたポケモンの名前のリストと文字頻度を用いて好きなようにWordleを解くアルゴリズムを書けば良いです．私は単純に出現頻度の高い文字をなるべく多く持つポケモンを出力するようにしました．この部分のコードは長くなるのと，多分最適解ではないので，修正して別の記事で解説しようと思います．

ちなみに現状の初手の最適解は「ジーランス」になりました笑
## 結果
![](https://i.imgur.com/xxNX1Or.png)
こんな感じになりした．
一手目は「ー」「ン」「ラ」「ス」を含むジーランス，ここで「ー」「ラ」「ン」がヒットしたので，候補は

- ユンゲラー
- キングラー
- ランターン
- グラードン
- レントラー
- ヒードラン

になります．この中の文字で一番出現頻度が高いものを探させると，「ド」となり，
二手目はグラードンになります．これを入力すると，新たに「グ」もヒットしたことがわかりました．これらの条件を満たすポケモンはキングラーしかいません．

文字頻度表ですが，これは同じポケモンの文字の重複をカウントしています(「マッスグマ」ならマで二回カウントしている).この点は修正したほうが良いかもしれません．

また，今回は出現頻度の高い文字を持つ順に選んでいきましたが，これは多分情報量の議論を用いて正確に選んだ方が精度は上がります(例えばジーランスの場合，「ジ」の出現頻度はだいぶ低いため，全体としては他のポケモンを選んだ方が効率的になる場合がある)．

時間がある時に修正しようと思います．