Pythonで無限の猿定理を考える

Python Monkey Typing Python

今日もCheckiOの問題を解いていきましょう。
今回の問題はこちら。

問題(Monkey Typing)

意味のある単語が含まれているかもしれないテキストから、いくつの単語が与えられたテキストに含まれているか調べる。

単語は全体が含まれている必要があり、他の単語の部分かもしれない。
大文字小文字は区別せず、単語は小文字で与えられるものとする。

同じ単語が複数回出現しても1度しか数えない。

入力:2つの引数。 文字列のテキストと、単語の文字列の集合(set)
出力:テキスト中の単語の数を表す整数
例:

count_words("How aresjfhdskfhskd you?", {"how", "are", "you", "hello"}) == 3
count_words("Bananas, give me bananas!!!", {"banana", "bananas"}) == 2
count_words("Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
            {"sum", "hamlet", "infinity", "anything"}) == 1


無限の猿定理を題材にした問題。
無限の猿定理とは猿にずーっとキーボードをランダムに叩かせれば、そのうち「ハムレット」と同じものができる可能性もあるという定理である。

みゅう
仮に1秒間に10万文字打てるとしても、100文字の文章が現れるまで100億年の1無量大数倍の1000京倍かかるらしいですよ。
室井
恐ろしく速いタイピング オレでなきゃ見逃しちゃうね

僕のコード

def count_words(text: str, words: set) -> int:
    cnt = 0
    for i in words:
        if i in text.lower():
            cnt += 1
    return cnt

考えたこと

文字列[i]と単語[j]を比較して、一致していたら文字列[i+1]と単語[j+1]を比較して…
最後までヒットしなかったらi++して繰り返す。
僕が授業で習った検索のアルゴリズムはこんな感じでした。

なので、すべての単語で上記のアルゴリズムを適用させようかと考えました。
が、思いとどまりました。

setは順番を持たないので、words[0]といった指定で取り出せません。
words = list(words)でリストに変換すれば取り出せますが、出題者の意図を読み取れていない気がします。

for文で単語をiに代入して回して、テキストに含まれていたらカウントすることにしました。
単語は小文字に統一されているため、テキストを小文字に変換しています。

わざわざ1文字ずつ比較しなくてもinを使えば簡単にできますね。

あとがき

Pythonのfor文はなんでも使えるのですごい便利ですね。

他の言語だとforeachに相当するらしいです。
もっと早くこいつの存在を知りたかったなぁ。