Python 列表中所有可能的总和,每个列表中只求和一个条目
我正在用Python编写一个练习程序,用给定的一组盘子计算我可以放在架子上的所有不同重量Python 列表中所有可能的总和,每个列表中只求和一个条目,python,list,math,Python,List,Math,我正在用Python编写一个练习程序,用给定的一组盘子计算我可以放在架子上的所有不同重量 def Weights(t=1,f=1,tn=1,tf=1,thf=1,ff=1,b=45): Max=b+5*t+10*f+20*tn+50*tf+70*thf+90*ff Poss=range(b,Max+1,5) ts=(list((i*5 for i in range(0,t+1)))) fs=(list((i*10 for i in range(0,f+1)))) tns=
def Weights(t=1,f=1,tn=1,tf=1,thf=1,ff=1,b=45):
Max=b+5*t+10*f+20*tn+50*tf+70*thf+90*ff
Poss=range(b,Max+1,5)
ts=(list((i*5 for i in range(0,t+1))))
fs=(list((i*10 for i in range(0,f+1))))
tns=(list((i*20 for i in range(0,tn+1))))
tfs=(list((i*50 for i in range(0,tf+1))))
thfs=(list((i*70 for i in range(0,thf+1))))
ffs=(list((i*90 for i in range(0,ff+1))))
Weights()
这给我留下了6张清单。要获得所有的组合,我需要将一个列表的一个元素与另一个列表的一个元素相加。在这一点上,这显然是一个线性代数问题,我只是不知道如何用Python来表达,特别是因为我不想使用插件(无NumPy)我认为你的方法是错误的,而且你的签名设计也很糟糕:如果你有7种不同的权重呢?我认为输入为元组列表(权重、最大值)更合适。当你开始这样思考时,你就会明白“交叉连接”7个列表也是错误的方法。你想要的是有一个所有简单权重的列表,然后得到所有子集。在Python中有一些很好的power set实现。我特别喜欢这个,因为它不会强制在内存中生成整个电源集,这可能是一个问题:
def功率序列(val):
''为可由整数索引的序列类型生成一个'powerset'。
使用二进制计数枚举成员并返回列表
示例:
>>>powersequence('STR')#字符串
['''S','T','ST','R','SR','TR','STR']
>>>功率序列([0,1,2])#列表
[[], [0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2]]
>>>幂序列((3,4,5))#元组
[(), (3,), (4,), (3, 4), (5,), (3, 5), (4, 5), (3, 4, 5)]
>>>
'''
vtype=类型(val);vlen=len(val);vrange=范围(vlen)
返回[reduce(λx,y:x+y,(val[i:i+1]表示变量范围中的i,如果2**i&n),vtype())
对于范围内的n(2**vlen)]
或者,您可以使用实践中更快的方法构建一个(多亏了umutto)
def功率序列(val):
s=列表(iterable)
返回链。从_iterable(范围(len(s)+1)内r的组合(s,r))
因此,算法是:
ts
,fs
,…)powersequence
生成功率集def所有权重(ws):
simpleWeights=[0]#只添加一次0
对于ws中的(w,c):
SimpleLights=SimpleLights+[w]*c
allWeights=(powersequence中子集的总和(子集)(simpleWeights))
返回集(所有权重)#过滤器唯一性
all=所有权重([(1,1)、(5,1)、(10,1)、(20,1)、(50,1)、(70,1)、(90,1)])
对于所有的w:
打印(w)
请注意,唯一性条件强制将整个集合具体化到内存中,所以这可能是此代码可以解决的问题大小的限制因素
更新
事实上,jez是对的:按硬币生成列表的速度将明显快于迭代连接列表的powersequence
def所有权重(ws):
simpleWeights=[]
对于ws中的(w,c):
append(列表((i*w表示范围(0,c+1)中的i)))
allWeights=(itertools.product(*simpleWeights)中子集的总和(子集))#注意simpleWeights前面的“*”!
返回集(所有权重)#过滤器唯一性
我认为你的方法是错误的,而且你的签名是糟糕的设计:如果你有7种不同的重量呢?我认为输入为元组列表(权重、最大值)更合适。当你开始这样思考时,你就会明白“交叉连接”7个列表也是错误的方法。你想要的是有一个所有简单权重的列表,然后得到所有子集。在Python中有一些很好的power set实现。我特别喜欢这个,因为它不会强制在内存中生成整个电源集,这可能是一个问题:
def功率序列(val):
''为可由整数索引的序列类型生成一个'powerset'。
使用二进制计数枚举成员并返回列表
示例:
>>>powersequence('STR')#字符串
['''S','T','ST','R','SR','TR','STR']
>>>功率序列([0,1,2])#列表
[[], [0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2]]
>>>幂序列((3,4,5))#元组
[(), (3,), (4,), (3, 4), (5,), (3, 5), (4, 5), (3, 4, 5)]
>>>
'''
vtype=类型(val);vlen=len(val);vrange=范围(vlen)
返回[reduce(λx,y:x+y,(val[i:i+1]表示变量范围中的i,如果2**i&n),vtype())
对于范围内的n(2**vlen)]
或者,您可以使用实践中更快的方法构建一个(多亏了umutto)
def功率序列(val):
s=列表(iterable)
返回链。从_iterable(范围(len(s)+1)内r的组合(s,r))
因此,算法是:
ts
,fs
,…)powersequence
生成功率集def所有权重(ws):
simpleWeights=[0]#只添加一次0
对于ws中的(w,c):
SimpleLights=SimpleLights+[w]*c
allWeights=(powersequence中子集的总和(子集)(simpleWeights))
返回集(所有权重)#过滤器唯一性
all=所有权重([(1,1)、(5,1)、(10,1)、(20,1)、(50,1)、(70,1)、(90,1)])
对于所有的w:
打印(w)
请注意,唯一性条件强制将整个集合具体化到内存中,所以这可能是此代码可以解决的问题大小的限制因素
更新
事实上,jez是对的:按硬币生成列表的速度将明显快于迭代连接列表的powersequence
def所有权重
import itertools
b = [45] # I assume this represents the "bar" and that it's not optional
ts = [0, 5, 10, 15]
fs = [0, 10]
combos = itertools.product(b, ts, fs)
for combo in combos: print(list(combo))
[45, 0, 0]
[45, 0, 10]
[45, 5, 0]
[45, 5, 10]
[45, 10, 0]
[45, 10, 10]
[45, 15, 0]
[45, 15, 10]
totals = [sum(combo) for combo in itertools.product(b, ts, fs)]
import itertools
def PossibleWeights(*weights):
return list(itertools.product(*[[weightset] if isinstance(weightset, (int, float)) else [sum(weightset[:i]) for i in range(len(weightset)+1)] for weightset in weights]))
d = {}
for combo in PossibleWeights( 45, [10]*2, [5]*3 ):
d[sum(combo)] = combo
for total, combo in sorted(d.items()):
print('sum(%r) = %r' % (combo, total))
sum((45, 0, 0)) = 45
sum((45, 0, 5)) = 50
sum((45, 10, 0)) = 55
sum((45, 10, 5)) = 60
sum((45, 20, 0)) = 65
sum((45, 20, 5)) = 70
sum((45, 20, 10)) = 75
sum((45, 20, 15)) = 80