5

Pythonでモリスシーケンスを生成しようとしています。私の現在の解決策は以下ですが、Pythonでcを書いたような気がします。誰もがよりpythonicなソリューションを提供できますか?

def morris(x):
    a = ['1', '11']
    yield a[0]
    yield a[1]
    while len(a) <= x:
        s = ''
        count = 1
        al = a[-1]
        for i in range(0,len(al)):
            if i+1 < len(al) and al[i] == al[i+1]:
                count += 1
            else:
                s += '%s%s' % (count, al[i])
                count = 1
        a.append(s)
        yield s
a = [i for i in morris(30)]
4

2 に答える 2

24

itertools.groupby完璧にフィットするようです!next_morris次のように関数を定義するだけです。

def next_morris(number):
    return ''.join('%s%s' % (len(list(group)), digit)
                   for digit, group in itertools.groupby(str(number)))

それで全部です!!!見て:

print next_morris(1)
11
print next_morris(111221)
312211

それを使用してジェネレーターを作成できます。

def morris_generator(maxlen, start=1):
    num = str(start)
    while len(num) < maxlen:
        yield int(num)
        num = next_morris(num)

使用法:

for n in morris_generator(10):
    print n

結果:

1
11
21
1211
111221
312211
13112221
于 2009-02-16T18:07:12.907 に答える
6
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

あなたがそれを好きになることを願っています!

于 2009-02-16T18:01:25.573 に答える