迭代Python 3中的和组合

时间:2013-03-29 10:43:07

标签: python itertools

我正在寻找一种方法来找到所有和的组合,其中Fibonacci序列的元素具有等于相同值的给定限制。我知道来自combinations()的{​​{1}}是解决此类问题的最佳选择,但由于我是Python的新手,我想知道如何保留匹配组合(因为只有一个是正确的,因为这不是算法的结束)。

我目前有:

itertools

现在我知道第二位在很多方面都是错误的。另外,我犯了一个错误,试图将元组添加到整数。我只需要知道如何使用itertools模块分别迭代这些组合的单独元素。只有sum'n'的组合对我有用。

3 个答案:

答案 0 :(得分:1)

如果我正确理解您要实现的目标,请使用以下代码:

def zeckendorf(n):
    seq = fib1(n)
    for i in range(1, len(seq)):
        for comb in itertools.combinations(seq, i):
            if sum(comb) == n:
                return list(comb)
    return []

如果您需要进一步解释此代码,请询问:)

答案 1 :(得分:1)

要查找所有所需总和的组合,请将每个组合附加到结果列表中:

def combinations_with_sum(sequence, desired_sum):
    results = []
    for i in range(len(sequence)):
        results.extend([combination for combination in combinations(sequence, i)
                        if sum(combination) == desired_sum])
    return results

答案 2 :(得分:0)

让我们假设您要查找输入的所有子集,并且< max_sum以及min_termsmax_terms之间的元素数量。

以下是一些方法,我包括整个脚本,以便更容易测试和使用,但基本上你只需要* LimitedSums()函数来获得答案。

蛮力方法是iterate through all subsets并检查每个子集的总和和元素数量。这实际上是SlowLimitedSums()所做的 - 尽管它利用itertools.combinations()来迭代子集,并且不会考虑具有超过max_terms个元素的子集。

潜在的更有效的方法是仅考虑总和小于max_sum的子集。如果要递归构建子集,只要当前子集的总和超过max_sum,就可以立即停止递归,假设所有输入数字都是非负数,或者元素数超过max_terms。这是在FasterLimitedSums()

中实现的

请注意,在最糟糕的情况下,您的结果将包含所有2^len(v)个子集 - 在这种情况下,*LimitedSums()的两个版本之间不应存在显着的运行时间差异。

import itertools
import random


def SlowLimitedSums(v, max_sum, min_terms=None, max_terms=None):
  min_terms = 0 if min_terms is None else min_terms
  max_terms = len(v) if max_terms is None else max_terms
  return sorted(set(
      sum(c) for nc in range(min_terms, max_terms + 1)
      for c in itertools.combinations(v, nc)
      if sum(c) <= max_sum))


def FasterLimitedSums(v, max_sum, min_terms=None, max_terms=None):
  l = sorted(v)
  n = len(v)
  min_terms = 0 if min_terms is None else min_terms
  max_terms = n if max_terms is None else max_terms
  result = set([])

  def RecursiveSums(s, n_terms, start_pos):
    if start_pos >= n or s > max_sum or n_terms > max_terms:
      return
    if n_terms >= min_terms:
      result.add(s)
    for p in range(start_pos, n):
      RecursiveSums(s + v[p], n_terms + 1, p + 1)

  RecursiveSums(0, 0, -1)
  return sorted(result)


def main():
  mass_list = [4, 1, 8]
  mass = 10
  print(sorted(mass_list + SlowLimitedSums(mass_list, mass, min_terms=2)))
  print(sorted(mass_list + FasterLimitedSums(mass_list, mass, min_terms=2)))


if __name__ == "__main__":
  main()