from itertools import groupby, islice
def morris():
morris = '1'
yield morris
while True:
morris = groupby(morris)
morris = ((len(list(group)), key) for key, group in morris)
morris = ((str(l), k) for l, k in morris)
morris = ''.join(''.join(t) for t in morris)
yield morris
print list(islice(morris(), 10))
まず、イテレータを無限にし、消費者にどれだけ欲しいかを決めさせます。そうすれば、彼はxより短いすべてのモリス数または最初のx数などを取得できます。
n := f(n-1)
そうすれば、再帰はとにかくのみであるため、以前のモリス番号のリスト全体をリストに格納する必要がないことは明らかです。
最後に、itertoolsを使用して機能的なタッチを与えることは、常に1つか2つのオタクポイントの価値があります;)ジェネレーター式をいくつかの行に分割して、見やすくします。
このソリューションの主な醜さはlen()
、イテレータで呼び出すことができないという事実に由来し、strが必要な場所にintを提供します。もう1つのヒックアップは、ネストされたstr.join)で、全体を再びstrにフラット化します。
任意の数からシーケンスを開始する場合は、次のように関数を定義します。
def morris(morris=None):
if morris is None:
morris = '1'
[...]
そのジェネレーターを好転させたい場合は、次のように書くことができます。
def morris():
morris = '1'
yield morris
while True:
print morris
morris = ''.join(''.join(t)
for t in ((str(len(list(group))), key)
for key, group in groupby(morris)))
yield morris
2つの関数に分割するのが好きかどうかはわかりませんが、これが最も読みやすい解決策のようです。
def m_groupby(s):
for key, group in groupby(s):
yield str(len(list(group)))
yield key
def morris():
morris = '1'
yield morris
while True:
morris = ''.join(m_groupby(morris))
yield morris
あなたがそれを好きになることを願っています!