0
我最近一直在與一些代碼,最近這涉及一個迭代打轉轉:2.7.6
"""IntegerPartitions.py
Generate and manipulate partitions of integers into sums of integers.
D. Eppstein, August 2005.
https://www.ics.uci.edu/~eppstein/PADS/IntegerPartitions.py
"""
def mckay(n):
"""
Integer partitions of n, in reverse lexicographic order.
The output and asymptotic runtime are the same as mckay(n),
but the algorithm is different: it involves no division,
and is simpler than mckay, but uses O(n) extra space for
a recursive call stack.
"""
if n == 0:
yield []
if n <= 0:
return
for p in mckay(n-1):
if len(p) == 1 or (len(p) > 1 and p[-1] < p[-2]):
p[-1] += 1
yield p
p[-1] -= 1
p.append(1)
yield p
p.pop()
該方案需要一個整數,並返回發生器輸出該整數的分區。
但是,當我嘗試在代碼中使用它時,我發現有些奇怪的東西。
>>> p = mckay(4)
>>> print list(p)
[[], [], [], [], []]
>>> q = mckay(4)
>>> cumulator = []
>>> for x in q :
... cumulator.append(x)
>>> print cumulator
[[], [], [], [], []]
>>> print list(mckay(4))
[[], [], [], [], []]
>>> r = mckay(4)
>>> for x in r :
... print x
[4]
[3, 1]
[2, 2]
[2, 1, 1]
[1, 1, 1, 1]
>>> for x in mckay(4) :
... print x
[4]
[3, 1]
[2, 2]
[2, 1, 1]
[1, 1, 1, 1]
除非我逐一打印,否則分區似乎不會顯示出來。這是一個語言中的錯誤(我的版本是Ubuntu Trusty上的Python 2.7.6),還是有我缺少的東西?我在Google上四處瀏覽,似乎無法找到與此相關的任何內容。
我認爲它可能有一些做的遞歸調用,但我用下面的代碼試了一下,發現了類似的結果
def mckay(n):
"""
Integer partitions of n, in reverse lexicographic order.
Note that the generated output consists of the same list object,
repeated the correct number of times; the caller must leave this
list unchanged, and must make a copy of any partition that is
intended to last longer than the next call into the generator.
The algorithm follows Knuth v4 fasc3 p38 in rough outline.
"""
if n == 0:
yield []
if n <= 0:
return
partition = [n]
last_nonunit = (n > 1) - 1
while True:
yield partition
if last_nonunit < 0:
return
if partition[last_nonunit] == 2:
partition[last_nonunit] = 1
partition.append(1)
last_nonunit -= 1
continue
replacement = partition[last_nonunit] - 1
total_replaced = replacement + len(partition) - last_nonunit
reps,rest = divmod(total_replaced,replacement)
partition[last_nonunit:] = reps*[replacement]
if rest:
partition.append(rest)
last_nonunit = len(partition) - (partition[-1]==1) - 1
的結果幾乎是一致的:
>>> p = mckay(4)
>>> print list(p)
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> q = mckay(4)
>>> cumulator = []
>>> for x in q :
... cumulator.append(x)
>>> print cumulator
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> print list(mckay(4))
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> r = mckay(4)
>>> for x in r :
... print x
[4]
[3, 1]
[2, 2]
[2, 1, 1]
[1, 1, 1, 1]
>>> for x in mckay(4) :
... print x
[4]
[3, 1]
[2, 2]
[2, 1, 1]
[1, 1, 1, 1]