返回一个变量长度的序列,其总和等于给定的整数

时间:2011-03-31 20:32:26

标签: python math permutation combinations

f(x,y,z)形式中,x是给定的整数和,y是序列的最小长度,z是序列的最大长度。但是现在让我们假装我们正在处理一个固定长度的序列,因为否则我需要很长时间才能写出这个问题。

所以我们的函数是f(x,r),其中x是给定的整数和,r是可能序列列表中序列的长度。

对于x = 10r = 2,这些是可能的组合:

1 + 9
2 + 8
3 + 7
4 + 6
5 + 5

让我们将它作为对列表存储在Python中:

[(1,9), (2,8), (3,7), (4,6), (5,5)]

所以用法如下:

>>> f(10,2)
[(1,9), (2,8), (3,7), (4,6), (5,5)]

回到原始问题,其中为(y,x)范围内的每个长度返回一个序列。我之前定义的格式为f(x,y,z),并且遗漏了长度1(其中y-z == 0)的序列,这看起来像:

>>> f(10,1,3)
[{1: [(1,9), (2,8), (3,7), (4,6), (5,5)],
  2: [(1,1,8), (1,2,7), (1,3,6) ... (2,4,4) ...],
  3: [(1,1,1,7) ...]}]

因此输出是字典列表,其中值是对列表。不完全是最佳的。

所以我的问题是:

  1. 是否有可以处理此问题的库?
  2. 如果没有,有人可以帮我写下我提到的两个功能吗? (首先是固定序列长度)?
  3. 由于我对相当琐碎的数学知识存在巨大差距,您是否可以忽略我对整数存储的方法并使用最有意义的结构?
  4. 今天对所有这些算术问题感到抱歉。谢谢!

3 个答案:

答案 0 :(得分:2)

itertools模块肯定会有用,因为我们正在处理预演 - 然而,这看起来像是一项家庭作业......

编辑:看起来很有趣,所以我会尝试。

编辑2 :这是你想要的吗?

from itertools import combinations_with_replacement
from pprint import pprint

f = lambda target_sum, length: [sequence for sequence in combinations_with_replacement(range(1, target_sum+1), length) if sum(sequence) == target_sum]

def f2(target_sum, min_length, max_length):
    sequences = {}
    for length in range(min_length, max_length + 1):
        sequence = f(target_sum, length)
        if len(sequence):
            sequences[length] = sequence
    return sequences

if __name__ == "__main__":
    print("f(10,2):")
    print(f(10,2))
    print()
    print("f(10,1,3)")
    pprint(f2(10,1,3))

输出:

f(10,2):
[(1, 9), (2, 8), (3, 7), (4, 6), (5, 5)]

f(10,1,3)
{1: [(10,)],
 2: [(1, 9), (2, 8), (3, 7), (4, 6), (5, 5)],
 3: [(1, 1, 8),
     (1, 2, 7),
     (1, 3, 6),
     (1, 4, 5),
     (2, 2, 6),
     (2, 3, 5),
     (2, 4, 4),
     (3, 3, 4)]}

答案 1 :(得分:1)

这个问题被称为 Integer Partitions ,并且已被广泛研究。

Here 您可以找到一篇文章,比较几种算法的性能(并提出一个特定的算法),但网上有很多参考文献。

答案 2 :(得分:0)

我刚写了一个递归生成器函数,你应该弄清楚如何从中获取一个列表......

def f(x,y):
    if y == 1:
        yield (x, )
    elif y > 1:
        for head in range(1, x-y+2):
            for tail in f(x-head, y-1):
                yield tuple([head] + list(tail))

def f2(x,y,z):
    for u in range(y, z+1):
        for v in f(x, u):
            yield v

编辑:我只是看到它不是你想要的,我的版本也会生成重复项,只有订单不同。但您可以通过排序所有结果并检查重复的元组来简单地过滤掉它们。