Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
给定k个分区的Python整数分区_Python_Algorithm_Integer Partition - Fatal编程技术网

给定k个分区的Python整数分区

给定k个分区的Python整数分区,python,algorithm,integer-partition,Python,Algorithm,Integer Partition,我正在尝试为Python寻找或开发整数分区代码 仅供参考,整数分区将给定的整数n表示为小于n的整数之和。例如,整数5可以表示为4+1=3+2=3+1+1=2+2+1=2+1+1=1+1+1=1+1+1 def part(n, k): def _part(n, k, pre): if n <= 0: return [] if k == 1: if n <= pre:

我正在尝试为Python寻找或开发整数分区代码

仅供参考,整数分区将给定的整数n表示为小于n的整数之和。例如,整数5可以表示为
4+1=3+2=3+1+1=2+2+1=2+1+1=1+1+1=1+1+1

def part(n, k):
    def _part(n, k, pre):
        if n <= 0:
            return []
        if k == 1:
            if n <= pre:
                return [[n]]
            return []
        ret = []
        for i in range(min(pre, n), 0, -1):
            ret += [[i] + sub for sub in _part(n-i, k-1, i)]
        return ret
    return _part(n, k, n)
我已经找到了很多解决方案。及

然而,我真正想要的是限制分区的数量

比如说,分区k=2的#,一个程序只需要显示
5=4+1=3+2

如果k=3,
5=3+1+1=2+2+1

def part(n, k):
    def _part(n, k, pre):
        if n <= 0:
            return []
        if k == 1:
            if n <= pre:
                return [[n]]
            return []
        ret = []
        for i in range(min(pre, n), 0, -1):
            ret += [[i] + sub for sub in _part(n-i, k-1, i)]
        return ret
    return _part(n, k, n)
更新

使用备忘录:

def part(n, k):
    def memoize(f):
        cache = [[[None] * n for j in xrange(k)] for i in xrange(n)]
        def wrapper(n, k, pre):
            if cache[n-1][k-1][pre-1] is None:
                cache[n-1][k-1][pre-1] = f(n, k, pre)
            return cache[n-1][k-1][pre-1]
        return wrapper

    @memoize
    def _part(n, k, pre):
        if n <= 0:
            return []
        if k == 1:
            if n <= pre:
                return [(n,)]
            return []
        ret = []
        for i in xrange(min(pre, n), 0, -1):
            ret += [(i,) + sub for sub in _part(n-i, k-1, i)]
        return ret
    return _part(n, k, n)
def部件(n,k):
def记忆(f):
缓存=[[[None]*n表示xrange中的j(k)]表示xrange中的i(n)]
def包装(n、k、pre):
如果缓存[n-1][k-1][pre-1]为无:
缓存[n-1][k-1][pre-1]=f(n,k,pre)
返回缓存[n-1][k-1][pre-1]
返回包装器
@回忆
def_零件(n、k、pre):

如果n我已经写了一个生成器解决方案

def partitionfunc(n,k,l=1):
    '''n is the integer to partition, k is the length of partitions, l is the min partition element size'''
    if k < 1:
        raise StopIteration
    if k == 1:
        if n >= l:
            yield (n,)
        raise StopIteration
    for i in range(l,n+1):
        for result in partitionfunc(n-i,k-1,i):
            yield (i,)+result
def partitionfunc(n,k,l=1):
''n是分区的整数,k是分区的长度,l是最小分区元素大小''
如果k<1:
提出停止迭代
如果k==1:
如果n>=l:
产量(n,)
提出停止迭代
对于范围内的i(l,n+1):
对于分区函数(n-i,k-1,i)中的结果:
收益率(i,)+结果
这将生成长度为
k
n
的所有分区,每个分区的顺序从最小到最大


简单说明一下:通过
cProfile
,使用生成器方法似乎比使用falsetru的直接方法快得多,使用测试函数
lambda x,y:list(partitionfunc(x,y))
。在测试运行
n=50,k-5时,我的代码运行时间为.019秒,而直接法为2.612秒。

首先,我要感谢大家的贡献。 我来到这里需要一个生成整数分区的算法,具体如下:

生成一个数字的分区,将其精确划分为k个部分,但同时具有最小和最大约束。

因此,我修改了“蛇和咖啡”的代码,以适应这些新的要求:

def partition_min_max(n,k,l, m):
'''n is the integer to partition, k is the length of partitions, 
l is the min partition element size, m is the max partition element size '''
if k < 1:
    raise StopIteration
if k == 1:
    if n <= m and n>=l :
        yield (n,)
    raise StopIteration
for i in range(l,m+1):
    for result in partition_min_max(n-i,k-1,i,m):                
        yield result+(i,)


>>> x = list(partition_min_max(20 ,3, 3, 10 ))
>>> print(x)
>>> [(10, 7, 3), (9, 8, 3), (10, 6, 4), (9, 7, 4), (8, 8, 4), (10, 5, 5), (9, 6, 5), (8, 7, 5), (8, 6, 6), (7, 7, 6)]
def分区最小值最大值(n,k,l,m):
''n是分区的整数,k是分区的长度,
l是最小分区元素大小,m是最大分区元素大小“”
如果k<1:
提出停止迭代
如果k==1:
如果n=l:
产量(n,)
提出停止迭代
对于范围内的i(l,m+1):
对于分区_min_max(n-i,k-1,i,m)中的结果:
收益率结果+(i,)
>>>x=列表(分区最小值最大值(20,3,3,10))
>>>打印(x)
>>> [(10, 7, 3), (9, 8, 3), (10, 6, 4), (9, 7, 4), (8, 8, 4), (10, 5, 5), (9, 6, 5), (8, 7, 5), (8, 6, 6), (7, 7, 6)]

在前面的答案的基础上加上最大和最小约束,我们可以将其优化得更好一些。对于k=16、n=2048和m=128的eg,只有一个这样的分区满足约束(128+128+…+128)。但代码会搜索不必要的分支,以找到可以删减的答案

def partition_min_max(n,k,l,m):
#n is the integer to partition, k is the length of partitions, 
#l is the min partition element size, m is the max partition element size
    if k < 1:
        return
    if k == 1:
        if n <= m and n>=l :
            yield (n,)
        return
    if (k*128) < n: #If the current sum is too small to reach n
        return
    if k*1 > n:#If current sum is too big to reach n
        return
    for i in range(l,m+1):
        for result in partition_min_max(n-i,k-1,i,m):                
            yield result+(i,)
def分区最小值最大值(n,k,l,m):
#n是分区的整数,k是分区的长度,
#l是最小分区元素大小,m是最大分区元素大小
如果k<1:
返回
如果k==1:
如果n=l:
产量(n,)
返回
如果(k*128)n:#如果当前总和太大而无法达到n
返回
对于范围内的i(l,m+1):
对于分区_min_max(n-i,k-1,i,m)中的结果:
收益率结果+(i,)

您只需要一定数量的分区?是的,没错。假设
partitionfunc(n,k)
将给出长度为kWait的整数n的分区列表,您想要固定长度的分区,还是只生成一定数量的分区?分区k的长度将由用户输入以及n@DavidEisenstat这是一个与相关问题不同的问题,这是关于双重限制整数分区(尽管链接问题的标题有误导性)。您可以使用
return
而不是
raise StopIteration
。我更新了列表连接版本。仍然比代码慢,但有所改进。:)您可以将范围(l,n+1)中i的
更改为范围(l,n//k+1)中i的
,因为不能有大于n//k的k个部分。我发现了一个非递归解决方案:
如图所示,raise StopIteration
现在不推荐使用
raisestopIteration
应替换为
return
语句。