Python 从给定的一组数字中找出适用于某些规则的所有组合
我非常感谢您对以下问题的帮助: 我有一个数字列表和一本字典:Python 从给定的一组数字中找出适用于某些规则的所有组合,python,algorithm,statistics,Python,Algorithm,Statistics,我非常感谢您对以下问题的帮助: 我有一个数字列表和一本字典: my_list = [400, 200, 100, 50, 25] my_dict = {400: 8, 200:4, 100: 2, 50: 2, 25: 2} 我需要从我的_列表中的数字中找到所有可能的组合,它们应该应用以下规则: 组合中可能有相同的数字([400400400]是有效的组合) 顺序无关紧要([400200100]对我来说与[100200400]相同) 组合中的数字总和不得超过1200 my_dict[my_lis
my_list = [400, 200, 100, 50, 25]
my_dict = {400: 8, 200:4, 100: 2, 50: 2, 25: 2}
我需要从我的_列表中的数字中找到所有可能的组合,它们应该应用以下规则:
[400400400]
是有效的组合)[400200100]
对我来说与[100200400]
相同)my_dict[my_list_item]
的总和不应超过24(例如[400400400100]
无效,因为my_dict[400]+my_dict[400]+my_dict[100]=8+8+8+2=26,因此它不是有效的组合)
谢谢以下是使用迭代器递归执行此操作的代码,以避免在内存中保存太多内容
#! /usr/bin/env python3
def combs (numbers, value_of, max_numbers=1200, max_value=24, min_i=0):
if len(numbers) <= min_i:
yield []
else:
for comb in combs(numbers, value_of, max_numbers, max_value, min_i+1):
yield comb
comb_copy = [n for n in comb] # Copy to avoid sharing bugs.
numbers_sum = sum(comb)
values_sum = sum([value_of[i] for i in comb])
while True:
comb_copy.append(numbers[min_i])
numbers_sum += numbers[min_i]
if max_numbers < numbers_sum:
break
values_sum += value_of[numbers[min_i]]
if max_value < values_sum:
break
yield comb_copy
my_list = [400, 200, 100, 50, 25]
my_dict = {400: 8, 200:4, 100: 2, 50: 2, 25: 2}
for c in combs(my_list, my_dict):
print(c)
#/usr/bin/env蟒蛇3
def梳(数量、值、最大值=1200、最大值=24、最小值=0):
如果len(numbers)假设您想要“列表的每个组合都有重复”,我编写了一个代码来计算它
它使用while循环,每次递增组合长度计数器。
由于组合的长度可以无限增长,因此该指示器用于停止循环,当未找到单个组合时,循环将激活
from itertools import combinations_with_replacement
my_list = [400, 200, 100, 50, 25]
my_dict = {400: 8, 200:4, 100: 2, 50: 2, 25: 2}
final_list = []
combinationLength = 1
while True:
c = list(combinations_with_replacement(my_list, combinationLength)) #generate every combination of length combinationLength
countNextCombination = False #indicator to break the while loop
for combination in c:
if (sum(combination) <= 1200):
dicsum=0
for j in combination:
dicsum+=my_dict[j]
if (dicsum<=24):
final_list.append(list(combination))
countNextCombination = True
if countNextCombination == False: #if not a single combination was valid, finish the loop
break
combinationLength += 1
print (final_list)
从itertools导入组合并替换
我的清单=[4002001005025]
我的圣经={400:8200:4100:2,50:2,25:2}
最终清单=[]
组合长度=1
尽管如此:
c=列表(带替换的组合(my_列表,combinationLength))#生成每个长度组合combinationLength
countNextCombination=False#用于中断while循环的指示器
对于c中的组合:
如果使用itertools(sum(composition),则不需要递归解决方案。带有替换迭代器的组合将为您提供组合,您只需检查您的条件。根据您的要求,您将需要组合的幂集(即所有大小的组合):
例如:
from itertools import combinations_with_replacement as combine
my_list = [400, 200, 100, 50, 25]
my_dict = {400: 8, 200:4, 100: 2, 50: 2, 25: 2}
for size in range(2,len(my_list)+1):
for combo in combine(my_list, size):
if sum(combo) <= 1200 \
and sum(my_dict[c] for c in combo) <= 24:
print(combo)
请注意,这是一种非优化的蛮力方法,可能适用于小数据集,但随着数据量的增加,这将花费指数级的时间通过检查部分和和和/或使用meoization,这将跳过整个组合样本。您将如何手动完成?此外,这一部分还不太清楚-输出“组合”可能需要多长时间?很棒的代码:)但在遇到此类问题时,使用递归好吗。。。?我有一种感觉,直接计算组合将减少由所有递归引起的不必要的计算(即,有许多相同组合的重复)@KentaNomoto如果你被要求计算计数,像这样的递归非常可怕,因为输出可能非常大。但在这里,我们被要求实际找到这些组合。递归没有很多好的替代方法——你能做的最好的方法就是限制在产生大量输出时使用的内存量。哦,我现在明白了。对在这里,递归可能是最有效的方法。正如你所说的,与其他方法相比,从一个非常大的输入中使用的内存要少得多。@KentaNomoto注意,诀窍不仅仅是递归。它是递归和迭代器。这样,您只需保留在内存中生成组合的位置,而不是整个数据结构。仅仅递归地生成完整的数据集是行不通的,问题是“找到组合”,而不是“找到多少组合”。因此,你在回答一个不同的问题。@B你到底是什么意思?“final_list”变量是所有组合的列表。编辑:哦,我现在明白了,combinationLength变量的命名可能有点误导。它不是总组合的长度,而是保存组合长度的变量(例如[200100100]是组合长度为3)正确。我的错。在这种情况下,您可能最终在内存中保留的内存量非常大,以至于您的代码根本无法运行。
(400, 400)
(400, 200)
(400, 100)
(400, 50)
(400, 25)
...
(50, 50, 50, 50, 50)
(50, 50, 50, 50, 25)
(50, 50, 50, 25, 25)
(50, 50, 25, 25, 25)
(50, 25, 25, 25, 25)
(25, 25, 25, 25, 25)