Python 以某种方式迭代素数

Python 以某种方式迭代素数,python,combinations,itertools,Python,Combinations,Itertools,目前,我正在输出列表中的所有素数组合以及该子集的乘积,如下所示: from operator import mul from itertools import combinations primes = [2, 3, 5, 7, 11] for r in range(1,len(primes)): for combo in combinations(primes,r+1): print combo, reduce(mul, combo) 哪个输出 (2,) 2 (3

目前,我正在输出列表中的所有素数组合以及该子集的乘积,如下所示:

from operator import mul
from itertools import combinations

primes = [2, 3, 5, 7, 11]

for r in range(1,len(primes)):
    for combo in combinations(primes,r+1):
        print combo, reduce(mul, combo)
哪个输出

(2,) 2
(3,) 3
(5,) 5
(7,) 7
(11,) 11
(2, 3) 6
(2, 5) 10
(2, 7) 14
(2, 11) 22
(3, 5) 15
(3, 7) 21
(3, 11) 33
(5, 7) 35
(5, 11) 55
(7, 11) 77
(2, 3, 5) 30
(2, 3, 7) 42
(2, 3, 11) 66
(2, 5, 7) 70
(2, 5, 11) 110
(2, 7, 11) 154
(3, 5, 7) 105
(3, 5, 11) 165
(3, 7, 11) 231
(5, 7, 11) 385
(2, 3, 5, 7) 210
(2, 3, 5, 11) 330
(2, 3, 7, 11) 462
(2, 5, 7, 11) 770
(3, 5, 7, 11) 1155
(2, 3, 5, 7, 11) 2310
现在让我们假设我们正在查看以下块:

(2, 5, 7) 70
(2, 5, 11) 110
(2, 7, 11) 154
(3, 5, 7) 105
(3, 5, 11) 165
(3, 7, 11) 231
(5, 7, 11) 385
(2, 3, 5, 7) 210
(2, 3, 5, 11) 330
为了举例,我想迭代所有的组合,其中乘积是,“问题”是
组合
生成器以特定的顺序发出所有长度为
r
的元组。你想让他们以不同的顺序来。因此,您需要编写自己的
组合
生成器

这类生成器通常是递归编写的:要从
i
中发出所有
r
-长度组合,首先删除一个元素——第一个元素——然后从其余元素递归发出所有
(r-1)
-长度组合

现在,您要做的是在产品太大时停止递归,这样您就不会发出不必要的元组。不幸的是,通常编写这种生成器的方法不允许这样做,因为字典顺序与“乘积递增顺序”不同

这意味着您必须找到一种不同的递归方法,一种每次增加数字乘积的方法。稍微考虑一下,您应该会想到以下算法:

  • 从尽可能小的元组开始
  • 对于元组的每个索引,请尝试将其“向上提升”到下一个素数。只有在
    • 产品仍然低于限制,并且
    • 元组保持排序顺序
  • 这将为您提供一个新的元组开始,因此在它上递归
这可以按如下方式实现

from operator import mul
primes = [2, 3, 5, 7, 11]
primes_inorder = dict(zip(primes, primes[1:]))

def my_combinations(primes, r, N, start=None, prod=None):
    """Yield all sorted combinations of length `r`
       from the sorted list `primes`."""
    if start is None:
        start = primes[:r]
        prod = reduce(mul, start)
        if prod > N: return

    yield start

    for i, v in enumerate(start):
        next_v = primes_inorder.get(v, None)
        if next_v is None or (i+1 < r and next_v > start[i+1]):
            continue

        new_prod = prod / v * next_v
        if new_prod > N:
            continue

        new_start = start[:]
        new_start[i] = next_v
        for combination in my_combinations(primes, r, N, start=new_start, prod=new_prod):
            yield combination
从操作员导入mul
素数=[2,3,5,7,11]
素数_inoorder=dict(zip(素数,素数[1:]))
def my_组合(素数、r、N、开始=无、产品=无):
“”“生成长度为'r'的所有排序组合`
从已排序的列表“素数”中
如果“开始”为“无”:
开始=素数[:r]
生产=减少(多个,开始)
如果prod>N:返回
产量起点
对于枚举中的i,v(开始):
next\u v=素数\u顺序。get(v,无)
如果next_v为None或(i+1开始[i+1]):
持续
新产品=产品/v*下一个产品
如果新产品>N:
持续
新开始=开始[:]
新的开始[i]=下一个开始
对于my_组合中的组合(素数,r,N,start=new_start,prod=new_prod):
产量组合

如果你想在任意时间前进,就必须手动生成组合。这正是我担心的,这是Project Euler的问题之一吗?(只是出于好奇。)我不确定我将如何使用这个——和以前一样的两个循环?当我这样做时,似乎输出的元组太大了。@A有一天我添加了一些解释——现在有意义了吗?它似乎对我有用,并不是说我有一个大数据集来测试它。是的,它应该像
组合一样工作,除非现在你也通过
110
。我在我的组合(primes,r+1110)中将它称为for combo,它输出东西>=110@AOAOne啊,,错误:它发出第一个组合,即使该组合大于等于110。固定的。