Tatehito's Programming Blog

現役プログラマがITっぽいネタを書いてアウトプット欲を満たすブログ

名前が「ン」で終わるポケモンの数をRuby2.7の新機能「Enumerable#tally」を使って数えてみた

はじめに

開発・公開中の『ポケモンしりとり』は、ポケモンの名前を使ったしりとりです。ルールは通常のしりとりと同じなので、名前の語尾が「ン」で終わるポケモンを回答すると負けになってしまいます。

www.pokemon-shiritori.com

現在、ポケモンは809種類いて、しりとりゲームを成立させるには十分な数ですが、「"ン"で終わる名前のポケモンって結構いるイメージだけど、何匹いるんだろ?」と思い立ち、せっかくなので、Ruby2.7から追加される新機能Enumerable#tallyを使って調べてみることにしました。

Enumerable#tallyとは

Enumerable#tallyは、Ruby2.7から追加される「各要素の出現回数を数える」メソッドです。各要素の値がkeyに、各要素の数がvalueとなるハッシュを返します。

["a", "b", "c", "b"].tally
#=> {"a"=>1, "b"=>2, "c"=>1}

ちなみに、tallyは日本語で「集計」という意味だそうです。

www.ruby-lang.org

ソースコード

と、いうことで、さっそく書いてみました。Rubyのバージョンは2.7.0-preview1です。

簡単に説明すると、

  1. 全ポケモンの情報が記述されているJSONファイルを読み取る
  2. 読み取ったデータをもとに、名前の語尾だけを格納した配列をつくる
  3. つくった配列に対してtallyを呼び出す
  4. その結果をsortで昇順にソートする

というやり方です。tallyはハッシュを返しますが、最後にsortしているため、最終的には配列が返ります。

『ポケモンしりとり』のルールに則り、語尾が長音の場合はその直前の文字(「フリーザー」は「ザ」)で、小文字の場合は大文字に変換(「フェローチェ」は「エ」)してカウントします。

また、ついでに語尾だけでなく、頭文字の数も調べてみました。

# JSONファイルを読み込む
require 'json'
json_data = open('pokemon_data.json') do |io|
    JSON.load(io)
end

# 語尾変換用ハッシュ
conversion = {'' => '', 
            '' => '',
            '' => '',
            '' => '',
            '' => '',
            '' => '',
            '' => '',
            '' => '',
            '' => '',
            '2' => '',
            'Z' => '',
            '' => '',
            '' => ''}
            
puts '---語尾を数える---'
p json_data.map { |data|
    if data['name'][-1] == ''
        # 語尾が長音の場合
        data['name'][-2]
    elsif data['name'][-1] =~ /[ァィゥェォャュョッ2Z♂♀]/
        # 語尾が小文字・特殊文字の場合
        data['name'][-1].sub(/./,conversion)
    else
        data['name'][-1]
    end
}.tally.sort

puts '---頭文字を数える---'
p json_data.map { |data|
    data['name'][0]
}.tally.sort

ソースコードはGithubにも公開しました。

github.com

出力結果

こんな感じ↓になりました!ブログに張り付けるにあたって、見やすいように(そもそもが見づらいけど......)改行を入れています。

---語尾を数える---
[["ア", 17], ["イ", 21], ["ウ", 15], ["エ", 1], ["オ", 15], ["カ", 5], 
["ガ", 14], ["キ", 17], ["ギ", 2], ["ク", 18], ["グ", 16], ["ケ", 1], 
["ゲ", 5], ["コ", 18], ["ゴ", 5], ["サ", 2], ["ザ", 2], ["シ", 23], 
["ジ", 3], ["ス", 80], ["ズ", 5], ["ゼ", 1], ["ソ", 1], 
["ゾ", 1], ["タ", 12], ["ダ", 9], ["チ", 11], ["ツ", 7], ["テ", 4], 
["デ", 5], ["ト", 32], ["ド", 25], ["ナ", 16], ["ニ", 5], ["ヌ", 1], 
["ネ", 6], ["ノ", 6], ["バ", 4], ["パ", 10], ["ヒ", 1], 
["ビ", 3], ["ピ", 4], ["フ", 4], ["ブ", 5], ["プ", 10], 
["ベ", 2], ["ホ", 1], ["ボ", 7], ["ポ", 1], ["マ", 21], 
["ミ", 6], ["ム", 22], ["メ", 6], ["モ", 8], ["ヤ", 6], ["ユ", 7], 
["ヨ", 3], ["ラ", 38], ["リ", 18], ["ル", 77], ["レ", 3], ["ロ", 12], ["ワ", 1], 
["ン", 102]]

---頭文字を数える---
[["ア", 33], ["イ", 10], ["ウ", 11], ["エ", 20], ["オ", 22], ["カ", 28], 
["ガ", 12], ["キ", 18], ["ギ", 8], ["ク", 15], ["グ", 8], ["ケ", 10], 
["ゲ", 4], ["コ", 26], ["ゴ", 19], ["サ", 15], ["ザ", 1], ["シ", 18], 
["ジ", 17], ["ス", 13], ["ズ", 5], ["セ", 1], ["ゼ", 5], ["ソ", 4], 
["ゾ", 2], ["タ", 10], ["ダ", 12], ["チ", 15], ["ツ", 6], ["テ", 6],
["デ", 14], ["ト", 13], ["ド", 25], ["ナ", 10], ["ニ", 19], ["ヌ", 7], 
["ネ", 7], ["ノ", 3], ["ハ", 18], ["バ", 23], ["パ", 9], ["ヒ", 16], 
["ビ", 9], ["ピ", 8], ["フ", 25], ["ブ", 12], ["プ", 7], ["ヘ", 3], 
["ベ", 6], ["ペ", 6], ["ホ", 7], ["ボ", 5], ["ポ", 11], ["マ", 31], 
["ミ", 16], ["ム", 9], ["メ", 16], ["モ", 10], ["ヤ", 16], ["ユ", 8], 
["ヨ", 6], ["ラ", 19], ["リ", 8], ["ル", 10], ["レ", 11], ["ロ", 5], ["ワ", 7]]

「ン」で終わるポケモンは102匹

でした。

1割ちょっとのポケモンが「ン」で終わるポケモンということですね。ちなみに、全文字中、1位が「ン」の102、2位が「ス」の80、3位が「ル」の77でした。

CPUに勝つには「ル」と「ス」を使え!(確信)

こちらの記事でも書いたのですが、「ル」もしくは「ス」で終わるポケモンをできるだけ回答し、「ル」「ス」で始まるポケモンを枯渇させることがCPUに勝つ最善の方法だということが、今回の分析で改めて分かりました。

というのも、「ス」で終わるポケモンは80匹と多く、かつ「ス」で始まるポケモンは13匹と少ないです。つまり、「ス」で始まるポケモンは枯渇させやすいです。同じく、「ル」で終わるポケモンは77匹、「ル」で始まるポケモンは10匹で、枯渇させやすいです。

CPUに勝ちたければ、「ス」と「ル」のポケモンをたくさん覚えましょう!

blog.tatehitolog.com

「レックウザ」と「フリーザー」で必勝!?

たとえば、「ヤ」で終わるポケモンが何種類かいて、かつ「ヤ」で始まるポケモンが1種類もいないとすると、「ヤ」で終わるポケモンを答えた時点で勝利が確定します。...が、そんな必勝ポケモンはいませんでした。(たぶん)

しかし!

「ザ」で始まるポケモンは「ザングース」だけなのに対し、「ザ」で終わるポケモンは「レックウザ」と「フリーザー」の2匹います。つまり、「レックウザ」と「フリーザー」をどちらも回答してしまえばCPUに勝つことができます。これは大発見(!?)です!

おわりに

Ruby2.7の新機能Enumerable#tallyを使って遊んでみました。新機能は楽しいですね。

Enumerable#tallyは「競技プログラミングで便利そうだな~~」という印象を受けましたが、AtCoderのRubyのバージョンは2.3.3なので、使えません。残念~。

www.pokemon-shiritori.com