项目欧拉数35效率

时间:2014-08-07 18:43:26

标签: performance

https://projecteuler.net/problem=35

Project Euler上的所有问题都应该由程序在1分钟内解决。但是,我的解决方案的运行时间大约为3分钟。我在网上看到的其他解决方案在概念上与我的相似,但运行时间指数更快。任何人都可以帮助我提高代码效率/运行更快吗?

谢谢!

#genPrimes takes an argument n and returns a list of all prime numbers less than n
def genPrimes(n):
    primeList = [2]
    number = 3
    while(number < n):
        isPrime = True
        for element in primeList:
            if element > number**0.5:
                break
            if number%element == 0 and element <= number**0.5:
                isPrime = False
                break
        if isPrime == True:
            primeList.append(number)
        number += 2
    return primeList

#isCircular takes a number as input and returns True if all rotations of that number are prime
def isCircular(prime):
    original = prime
    isCircular = True
    prime = int(str(prime)[-1] + str(prime)[:len(str(prime)) - 1])
    while(prime != original):
        if prime not in primeList:
            isCircular = False
            break
        prime = int(str(prime)[-1] + str(prime)[:len(str(prime)) - 1])
    return isCircular

primeList = genPrimes(1000000)
circCount = 0
for prime in primeList:
    if isCircular(prime):
        circCount += 1
print circCount

1 个答案:

答案 0 :(得分:0)

对代码进行两次修改会产生一个非常快速的解决方案(在我的机器上大约2秒):

  1. 生成素数是网络上许多解决方案的常见问题。我使用this article中的rwh_primes1替换了你的

    def genPrimes(n):
        sieve = [True] * (n/2)
        for i in xrange(3,int(n**0.5)+1,2):
            if sieve[i/2]:
                sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
        return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]
    

    它快了约65倍(0.04秒)。

  2. 然而,我建议的最重要的一步是过滤生成的素数列表。由于整数的每个循环移位版本必须是素数,因此圆形素数不得包含某些数字。例如,素数23可以很容易地被发现为无效候选者,因为它包含2,当这是最后一位数时,它表示两个可分性。因此,您可以通过以下简单方法删除所有这些不良候选人:

    def filterPrimes(primeList):
        for i in primeList[3:]:
            if '0' in str(i) or '2' in str(i) or '4' in str(i) \
            or '5' in str(i) or '6' in str(i) or '8' in str(i):
                primeList.remove(i)
        return primeList
    

    请注意,循环从第四个素数开始,以避免删除数字25

    过滤步骤占用了大部分计算时间(约1.9秒),但是将循环质数候选者的数量从78498急剧减少到1113(减少了98.5%)!

  3. 最后一步,每个剩余候选人的流通,可以按照你的建议完成。如果您愿意,可以按如下方式简化代码:

    circCount = sum(map(isCircular, primeList))
    

    由于候选集减少,此步骤仅在0.03秒内完成。