【问题标题】:Iterate over lists with a particular sum迭代具有特定总和的列表
【发布时间】:2016-04-28 02:40:07
【问题描述】:

我想遍历所有长度为 n 且元素总和为 2 的列表。如何有效地做到这一点?这是n = 10 的一个非常低效的方法。最终我想为 `n > 25' 做这个。

n = 10
for L in itertools.product([-1,1], repeat = n):
    if (sum(L) == 2):
        print L #Do something with L

【问题讨论】:

  • 元素值可以是1-1吗?
  • @lambo477 是的,没错。

标签: python math optimization


【解决方案1】:

一种方法是在剩余元素无法构成目标总和时停止乘积递归。

具体来说,此方法会将您的 itertools.product(...,repeat) 拆分为递归生成器,该生成器会根据当前列表元素的值更新目标总和,并在进一步递归之前检查结果目标是否可以实现:

def generate_lists(target, n):
  if(n <= 0):
    yield []
    return
  if(target > n or target < -n):
    return
  for element in [-1,1]:
    for list in generate_lists(target-element, n-1):
      yield list+[element]

【讨论】:

  • 我认为你想要or 而不是|| ...这也几乎可以保证超过pythons递归堆栈限制(+1都是一样的,因为它适用于较小的列表...它从概念层面很好地解释了 OP 应该做什么)
【解决方案2】:

如果你的 +1 比 -1 多 2 个,那么你只能得到 2 的解,所以对于 n==24

a_solution = [-1,]*11 + [1,]*13  

现在你可以使用 itertools.permutations 来获得这个的每一个排列

for L in itertools.permutations(a_solution): print L

使用 itertools.combinations 消除重复可能会更快

for indices in itertools.combinations(range(24),11):
    a = numpy.ones(24)
    a[list(indices)] = -1
    print a

注意你得到 2 列表必须是偶数长度

【讨论】:

  • itertools.permutations 仍然会产生大量重复项。最好使用itertools.combinations为-1选择11个位置。
  • 请注意,它将是itertools.combinations(xrange(n), n//2-1),然后将 -1 放入所选位置。我们不会在a_solution 上致电combinations
  • ahh dang ... 现在我要打开一个 python 解释器
  • 更一般地,给定偶数n (>= 2):a_solution = [-1] * (n//2 - 1) + [1] * (n//2 + 1)
  • (另外,您可能应该使用 25 以外的数字。11+13=24。我们需要一个偶数长度。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多