如何在Python中有效地获得总和为10或以下的所有组合
假设您正试图在一些地区(例如如何在Python中有效地获得总和为10或以下的所有组合,python,itertools,Python,Itertools,假设您正试图在一些地区(例如t=5)上分配一些固定资源(例如n=10)。我试图找出如何有效地获得总和n或以下的所有组合 例如,10,0,0,0,0是好的,以及0,0,5,5,0等,而3,3,3,3,3显然是错误的 我走了这么远: import itertools t = 5 n = 10 r = [range(n+1)] * t for x in itertools.product(*r): if sum(x) <= n: print x 可能的
t=5
)上分配一些固定资源(例如n=10
)。我试图找出如何有效地获得总和n
或以下的所有组合
例如,10,0,0,0,0
是好的,以及0,0,5,5,0
等,而3,3,3,3,3
显然是错误的
我走了这么远:
import itertools
t = 5
n = 10
r = [range(n+1)] * t
for x in itertools.product(*r):
if sum(x) <= n:
print x
可能的办法如下。肯定会小心使用(几乎没有测试过,但n=10和t=5的结果看起来合理) 该方法不涉及递归。生成具有m个元素(示例中为5个)的数字n(示例中为10)的分区的算法来自Knuth的第4卷。如果需要,每个分区都会进行零扩展,所有不同的排列都是使用Aaron Williams的算法生成的,我已经看到了这个算法。这两种算法都必须翻译成Python,这增加了出错的可能性。Williams算法需要一个链表,为了避免编写链表类,我不得不用2D数组来伪造链表 有一个下午了 Code(注意您的
n
是我的maxn
,您的t
是我的p
):
导入itertools
def访问(上午、下午):
“”“将分区添加到列表的实用程序函数”“”
x、 追加(a[1:m+1])
def部件(a、n、m):
“Knuth算法H,组合算法,前分册3B
查找n个元素正好有m个元素的所有分区。
运行时间的上限为(3 x
找到分区)+m。不是递归的!
"""
而(一):
参观(上午、下午)
当a[2]=a[1]-1时:
s+=a[j]
j+=1
如果j>m:
打破
x=a[j]+1
a[j]=x
j-=1
当j>1时:
a[j]=x
s-=x
j-=1
a[1]=s
def distinct_perms(分区):
“Aaron Williams算法1,”多重集的无环生成
按前缀移位排列“。查找所有不同的排列
一张有重复项目的清单。我不完全按照报纸上说的去做
嗯,但它可能有一个成比例的运行时间
到置换的数量(每个置换有3个移位操作
平均排列)。不是递归的!
"""
perms=[]
val=0
nxt=1
l1=[[i]分区,i+1]表示范围内的i(len(分区))]
l1[-1][nxt]=无
#打印(l1)
水头=0
i=len(l1)-2
afteri=i+1
tmp=[]
tmp+=[l1[头部][val]]
c=头部
而l1[c][nxt]!=无:
tmp+=[l1[c][nxt][val]]
c=l1[c][nxt]
perms.extend([tmp])
而(l1[afteri][nxt]!=None)或(l1[afteri][val]=l1[l1[afteri][nxt][val]):
前后
其他:
beforek=i
k=l1[之前][nxt]
l1[beforek][nxt]=l1[k][nxt]
l1[k][nxt]=水头
如果l1[k][val]=2)
x=[[i]表示范围内的i(maxn+1)]
#主要案例:运行零件fn(最大^2+最大)/2次
对于范围(2,最大值+1)内的i:
对于范围(2,min(p+1,i+1))内的j:
m=j
n=i
a=[0,n-m+1]+[1]*(m-1)+[-1]+[0]*(n-m-1)
零件(a、n、m)
y=[]
#对于每个分区,如果需要,添加零,然后查找
#不同的排列。运行一次distinct_perms函数
#对于每个分区。
对于第x部分:
如果len(部分)
您可以使用动态规划优化算法
基本上,有一个数组a
,其中a[i][j]
的意思是“我可以得到j
的和,其中的元素一直到j-th
元素(并且使用jth
元素,假设您的元素在数组t
(不是您提到的数字))
然后你就可以填充数组了
a[0][t[0]] = True
for i in range(1, len(t)):
a[i][t[i]] = True
for j in range(t[i]+1, n+1):
for k in range(0, i):
if a[k][j-t[i]]:
a[i][j] = True
然后,使用此信息,您可以回溯解决方案:)
创建自己的递归函数,除非可以使sum=0,否则该函数不会与元素一起递归: 收益率 返回 对于r中的x:
如果x>n:#您可以使用
itertools
创建所有排列,并使用numpy
解析结果
>>> import numpy as np
>>> from itertools import product
>>> t = 5
>>> n = 10
>>> r = range(n+1)
# Create the product numpy array
>>> prod = np.fromiter(product(r, repeat=t), np.dtype('u1,' * t))
>>> prod = prod.view('u1').reshape(-1, t)
# Extract only permutations that satisfy a condition
>>> prod[prod.sum(axis=1) < n]
>>将numpy作为np导入
>>>来自itertools进口产品
>>>t=5
>>>n=10
>>>r=范围(n+1)
#创建产品numpy数组
>>>prod=np.fromiter(product(r,repeat=t),np.dtype('u1,*t))
>>>产品=产品视图('u1')。重塑(-1,t)
#仅提取满足条件的置换
>>>产品[prod.sum(轴=1)
时间:
>>> %%timeit
prod = np.fromiter(product(r, repeat=t), np.dtype('u1,' * t))
prod = prod.view('u1').reshape(-1, t)
prod[prod.sum(axis=1) < n]
10 loops, best of 3: 41.6 ms per loop
>>%%timeit
prod=np.fromiter(product(r,repeat=t),np.dtype('u1,*t))
产品=产品视图('u1')。重塑(-1,t)
产品[prod.sum(轴=1)
您甚至可以通过以下方式加快乘积计算。您想找到一个数字的所有和组合吗?@qqvc听起来不错?可能重复?这里的任务是找到所有的和。@Tony虽然有些想法可能适用,但问题是
def backtrack(j = len(t)-1, goal = n):
print j, goal
all_solutions = []
if j == -1:
return []
if goal == t[j]:
all_solutions.append([j])
for i in range(j-1, -1, -1):
if a[i][goal-t[j]]:
r = backtrack(i, goal - t[j])
for l in r:
print l
l.append(j)
all_solutions.append(l)
all_solutions.extend(backtrack(j-1, goal))
return all_solutions
backtrack() # is the answer
def f(r, n, t, acc=[]):
if t == 0:
if n >= 0:
yield acc
return
for x in r:
if x > n: # <---- do not recurse if sum is larger than `n`
break
for lst in f(r, n-x, t-1, acc + [x]):
yield lst
t = 5
n = 10
for xs in f(range(n+1), n, 5):
print xs
>>> import numpy as np
>>> from itertools import product
>>> t = 5
>>> n = 10
>>> r = range(n+1)
# Create the product numpy array
>>> prod = np.fromiter(product(r, repeat=t), np.dtype('u1,' * t))
>>> prod = prod.view('u1').reshape(-1, t)
# Extract only permutations that satisfy a condition
>>> prod[prod.sum(axis=1) < n]
>>> %%timeit
prod = np.fromiter(product(r, repeat=t), np.dtype('u1,' * t))
prod = prod.view('u1').reshape(-1, t)
prod[prod.sum(axis=1) < n]
10 loops, best of 3: 41.6 ms per loop