【问题标题】:Is there a more efficient way to find all combinations of 10 items in 10% increments?有没有更有效的方法以 10% 的增量查找 10 个项目的所有组合?
【发布时间】:2012-03-29 07:44:30
【问题描述】:

我正在分析 10 种货币,我想以 10% 的增量找出这些货币的所有可能组合。例如:

10% of A, 20% of B...etc 

约束如下:

总和必须达到 100% 每种货币可以有 0% 到 100% 之间的任意数量,所以 A 的 100% 的组合是有效的

目前我的代码如下所示:

for element in itertools.product(*curr_arr):
    if round(sum(element),1)==1:
        comb_input.append(list(element))

其中 curr_arr 本质上是一个数组,如下所示:

  [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]

这种方法非常慢,因为它会查看所有组合,然后提取总和为 1 的组合。有没有更有效的方法来执行此操作并加快我的代码速度?

【问题讨论】:

  • 如果可能,使用百分比 (10, 20, 30, ...) 而不是浮点数 (0.1, 0.2, 0.3, ...)。这些浮点数的总和并不是 1.0。:0.3+0.3+0.3+0.1 返回 0.99999999999999989

标签: python loops combinations


【解决方案1】:

这很难看,但它

combinations = []
for a in xrange(11):
    for b in xrange(11-a):
        for c in xrange(11-a-b):
            for d in xrange(11-a-b-c):
                for e in xrange(11-a-b-c-d):
                    for f in xrange(11-a-b-c-d-e):
                        for g in xrange(11-a-b-c-d-e-f):
                            for h in xrange(11-a-b-c-d-e-f-g):
                                for i in xrange(11-a-b-c-d-e-f-g-h):
                                    j = 10-a-b-c-d-e-f-g-h-i
                                    combinations.append((a,b,c,d,e,f,g,h,i,j))
print len(combinations)

这会在 0.2 秒内为您提供所有 92378 种组合。

请注意,它返回 0 到 10 之间的整数值,必须乘以 10 才能获得百分比。

【讨论】:

  • 我刚刚尝试过使用 range 而不是 xrange,每行的总和似乎为 11,即 110%。应该是 xrange(10) 吗?
  • @Mandeep - 不,这是计算 j 的行中的 11 -> 10。对此感到抱歉。现在修好了。 xranges 中的 11 是正确的。
【解决方案2】:

并非如此,您的问题基本上是Subset sum problem(给定一组整数,找到总和为k 的那些),而问题是NP-Complete。这意味着您找到比现在更好的算法的机会非常小。

我建议将这部分代码用 C 语言编写为 Python 扩展(请参阅 Extending and Embedding the Python Interpreter)并从您的 Python 代码中调用该函数。这应该会给您带来不错的速度提升。

【讨论】:

  • 好的,谢谢,我想解决这个问题的最快方法是运行一次代码以查找所有组合。将其导出到 excel 并过滤总和为 100% 的组合,然后在每次运行分析时重新导入这些组合
  • @Mandeep - 您不想将 10**10 个数据条目导出到 excel...
【解决方案3】:

如何找到所有给出 100% 的组合,然后找到这些组合的所有排列?我无法运行您的示例,因此我不确定它在速度方面的比较。

import itertools

curr_arr = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

comb_input = [a for a in itertools.combinations_with_replacement(curr_arr, 10) if sum(a) == 100]
comb_input = [set(itertools.permutations(a)) for a in comb_input]

finish = []
for a in comb_input:
    finish += list(a)

print len(finish)

【讨论】:

    【解决方案4】:
    for currencyA, currencyB, currencyC, currencyD, currencyE, currencyF, currencyG, currencyH, currencyI, currencyJ in itertools.permutations(range(0,101,10)):
        # you now have varying percentages of each currency
        # if sum of the currencies == 100
        # do whatever!
    

    【讨论】:

      【解决方案5】:

      可以直接生成总和为 100 % 的组合,无需过滤。使用my answer to a previous question

      comb_input = [[x/10.0 for x in y] for y in lists_with_sum(10, 10)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-23
        • 2016-11-05
        • 2020-12-14
        • 1970-01-01
        • 1970-01-01
        • 2020-11-16
        • 1970-01-01
        相关资源
        最近更新 更多