Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有效地生成小于N的所有复合数(及其分解)_Python_Algorithm_Iterator_Generator - Fatal编程技术网

Python 有效地生成小于N的所有复合数(及其分解)

Python 有效地生成小于N的所有复合数(及其分解),python,algorithm,iterator,generator,Python,Algorithm,Iterator,Generator,我想构建一个高效的Python迭代器/生成器,它可以生成: 小于N的所有组合数 以及它们的素因子分解 我称之为“带因子的复合” 假设我们已经有一个小于N的素数列表,或者一个素数生成器也可以这样做 请注意,我: 不需要按数字顺序生成数字 不管1是否在开始时产生 不要在意是否也产生了素数 我想这可以通过一个聪明的递归生成器来实现 因此,例如,调用带有_因子(16)的复合_可能会产生: # yields values in form of "composite_value, (factor_t

我想构建一个高效的Python迭代器/生成器,它可以生成:

  • 小于N的所有组合数
  • 以及它们的素因子分解
我称之为“带因子的复合”

假设我们已经有一个小于N的素数列表,或者一个素数生成器也可以这样做

请注意,我:

  • 不需要按数字顺序生成数字
  • 不管1是否在开始时产生
  • 不要在意是否也产生了素数
我想这可以通过一个聪明的递归生成器来实现

因此,例如,调用带有_因子(16)的复合_可能会产生:

# yields values in form of "composite_value, (factor_tuple)"
2, (2)
4, (2, 2)
8, (2, 2, 2)
6, (2, 3)
12, (2, 2, 3)
10, (2, 5)
14, (2, 7)
3, (3)
9, (3, 3)
15, (3, 5)
5, (5)
7, (7)
11, (11)
13, (13)
从我的输出顺序可以看出,我设想这样做,从可用素数生成器上的最小素数开始,输出该素数的所有幂次小于N,然后再次尝试该素数的幂次,但在每个阶段,看看是否可以应用附加素数的幂次(仍然小于N)。当所有与该素数的组合完成后,放下它,用素数生成器上可用的下一个最低素数重复

我试图用“递归生成器”来实现这一点,这让我非常困惑,什么时候用“yield”或“raisestopIteration”或“return”退出递归,或者干脆退出递归函数

谢谢你的智慧

补充说明:

我现在有一种方法可以做到这一点:我已经编写了一个函数来计算数字的因子,这样我就可以将它们分解为素数,并得到结果。没问题。我依靠一个缓存“N的最小素数因子是多少”来保持这个惊人的速度。。。一千万

然而,一旦我从缓存中出来,我们将,它将转移到“幼稚”的因子分解。(恶心。)

这篇文章的要点是:

  • 我假设“从它们的因子生成大型复合物”将比“分解大型复合物”更快。。。特别是因为我不在乎秩序,而且
  • 如何让Python生成器“递归地”调用自己,并生成一个生成的东西流
假设
primesiter(n)
n
之前的所有素数上创建一个迭代器(1不应包含在
primesiter
中,或以下代码完全进入inf.循环)

注意:它也包括n(=16),我使用列表而不是元组。如果需要,这两个问题都可以很容易地解决,但我将把它作为一个练习。

递归(伪代码):


这是一个基于筛的实现(请原谅非Python代码:):

在我的机器上,这花了56秒运行:

primes = sieve(14000000) # 14 million!
示例:

>>> primes[:10]
[[], [], [2], [3], [2, 2], [5], [2, 3], [7], [2, 2, 2], [3, 3]]

>>> primes[10000]
[2, 2, 2, 2, 5, 5, 5, 5]

>>> primes[65536]
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

>>> primes[6561]
[3, 3, 3, 3, 3, 3, 3, 3]

>>> primes[233223]
[3, 17, 17, 269]
内存消耗:大约5000万个整数,在1400万个列表中:

>>> sum(map(len, primes))
53303934

你对这种方法做了哪些努力?请给我们看看你的代码。你是制作素数生成器,还是只制作一个奇数生成器?如果你一次只做一件,也许会更容易理解。请给我们看一下您目前掌握的代码。@Makoto:我的尝试完全失败了,如果我发布沉船的话,将无法说明问题。例如,我的案例只产生了小于N的整数的一小部分。您提到您希望递归地执行此操作,但很难击败筛子。可以对其进行简单的修改,以保持因子不变。@Hooked:好的,我可以再次查看SoE。也许我可以“反转”它来产生复合物而不是素数。然而,我曾经尝试实现一个SoE(针对素数),据我观察,它占用了大量内存(因为每个阶段都需要“记住”将要过滤掉的内容)!这就是我无法理解的“递归生成器”。我所看到的让我困惑:a)我需要在一次函数调用中使用两个“for循环”,b)一个在“internal for循环”之前屈服,一个在“internal for循环”中屈服。做得很好。我需要更多地研究筛子,我将以此为例。(我仍然担心内存需求……但这可能是因为我很久以前(可能是糟糕的)将筛选阶段作为独立对象实现,每个阶段都有自己的内存需求。)谢谢。在我看来,这个伪代码基本上与@catchmeifyoutry的实现相同。(至于使用minp^2>end的测试:我有一种预感,这只是最微小的优化,因为下一次通过end=end/minp“in”到自身的递归将有效地捕获相同的条件。)
def sieve(n):
    # start each number off with an empty list of factors
    #   note that nums[n] will give the factors of n
    nums = [[] for x in range(n)]
    # start the counter at the first prime
    prime = 2
    while prime < n:
        power = prime
        while power < n:
            multiple = power
            while multiple < n:
                nums[multiple].append(prime)
                multiple += power
            power *= prime
        # find the next prime
        #   the next number with no factors
        k = prime + 1
        if k >= n:    # no primes left!!!
            return nums
        # the prime will have an empty list of factors
        while len(nums[k]) > 0:
            k += 1
            if k >= n:    # no primes left!!!
                return nums
        prime = k
    return nums


def runTests():
    primes = sieve(100)
    if primes[3] == [3]:
        print "passed"
    else:
        print "failed"
    if primes[10] == [2,5]:
        print "passed"
    else:
        print "failed"
    if primes[32] == [2,2,2,2,2]:
        print "passed"
    else:
        print "failed"
>>> runTests()
passed
passed
passed
primes = sieve(14000000) # 14 million!
>>> primes[:10]
[[], [], [2], [3], [2, 2], [5], [2, 3], [7], [2, 2, 2], [3, 3]]

>>> primes[10000]
[2, 2, 2, 2, 5, 5, 5, 5]

>>> primes[65536]
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

>>> primes[6561]
[3, 3, 3, 3, 3, 3, 3, 3]

>>> primes[233223]
[3, 17, 17, 269]
>>> sum(map(len, primes))
53303934