整数分区是一个非常有趣的主题。创建给定整数的所有分区几乎都很简单,例如以下代码:
def aP(n):
"""Generate partitions of n as ordered lists in ascending
lexicographical order.
This highly efficient routine is based on the delightful
work of Kelleher and O'Sullivan."""
a = [1]*n
y = -1
v = n
while v > 0:
v -= 1
x = a[v] + 1
while y >= 2 * x:
a[v] = x
y -= x
v += 1
w = v + 1
while x <= y:
a[v] = x
a[w] = y
yield a[:w + 1]
x += 1
y -= 1
a[v] = x + y
y = a[v] - 1
yield a[:w]
寻找一种方法来获得对该功能的更多控制,例如为了仅生成N大小的分区,这个解决方案看起来更好:
def sum_to_n(n, size, limit=None):
"""Produce all lists of `size` positive integers in decreasing order
that add up to `n`."""
if size == 1:
yield [n]
return
if limit is None:
limit = n
start = (n + size - 1) // size
stop = min(limit, n - size + 1) + 1
for i in range(start, stop):
for tail in sum_to_n(n - i, size - 1, i):
yield [i] + tail
但是它们都会生成给定数字的所有可能分区,第一个是每个大小,第二个是给定大小。如果我只想要给定数字的一个特定分区怎么办? 以下代码生成给定分区的下一个分区:
def next_partition(p):
if max(p) == 1:
return [sum(p)]
p.sort()
p.reverse()
q = [ p[n] for n in range(len(p)) if p[n] > 1 ]
q[-1] -= 1
if (p.count(1)+1) % q[-1] == 0:
return q + [q[-1]]*((p.count(1)+1) // q[-1])
else:
return q + [q[-1]]*((p.count(1)+1) // q[-1]) + [(p.count(1)+1) % q[-1]]
但仍有问题,您必须知道分区请求之前的分区是什么。
假设现在需要一个整数N的给定分区,你只知道分区的编号;例如:
4的分区是:
n.1 4
n.2 3+1
n.3 2+2
n.4 2+1+1
n.5 1+1+1+1
如何创建仅给出整数(4)和序列号(2)的分区号2(3 + 1)?所有这些都没有创建所有分区? 我已经阅读过某个可能的数学公式,但我不知道如何。