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 给它一个功能性的触摸总是值得一两个极客点;)我将生成器表达式分成几行以使其更容易看。
这个解决方案的主要丑陋之处在于len()
不能在迭代器上调用,并在我们需要 str 的地方给了我们一个 int。另一个小问题是嵌套的 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
我不确定我是否喜欢分成两个函数,但这似乎是最易读的解决方案:
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
希望你喜欢!