欧拉计画(37)

时间:2018-08-25 20:19:09

标签: python python-3.x

我试图解决Euler项目#37:

  

数字3797具有一个有趣的性质。作为素数本身,可以从左到右连续删除数字,并在每个阶段保持素数:3797、797、97和7。类似地,我们也可以从右到左:3797、379、37和3。   找出从左到右和从右到左都可以截断的十一个素数之和。   注意:2、3、5和7不被视为可截短的素数。

我用Python编写了代码,但遇到了奇怪的问题。 这是我的代码:

def isPrime(n):
    if n == 2 or n == 3 or n == 5: return True
    if n < 2 or n%2 == 0: return False
    if n < 9: return True
    if n%3 == 0: return False
    if n%5 == 0: return False
    r = int(n**0.5)
    f = 5
    while f <= r:
      if n%f == 0: return False
      if n%(f+2) == 0: return False
      f +=6
    return True

def gen(nb):
    results = []
    nb_str = str(nb)
    for k in range(0, len(nb_str) - 1):
        results.append(nb_str[k:])
        results.append(nb_str[-k:])
    return results

def check(nb):
    for t in gen(nb):
        if not isPrime(int(t)):
            return False
    return True

c = 0
s = 0
i = 2
while c != 11:
    if check(i):
        c += 1
        s += i
    i += 1
print(s)

错误来自哪里? (预期结果为748317)

我怀疑错误来自结果列表

2 个答案:

答案 0 :(得分:3)

是的,由于切片已关闭,gen()函数无法正常工作,另外,您将2357计为问题被拒绝的截断素数。

第二个切片应该相反:

>>> s = 'abcd'
>>> for i in range(1,len(s)-1):
...     print(s[i:])
...     print(s[:-i])
... 
bcd
abc
cd
ab
我们可以看到

产生正确的字符串。


总而言之,函数应该是:

def gen(nb):
    results = [nb]
    nb_str = str(nb)
    for k in range(1, len(nb_str)):
        results.append(int(nb_str[k:]))
        results.append(int(nb_str[:-k]))
    return results

请注意,我还向int转换中添加了一个字符串-不知道Python如何无法使您明显://


在获得完整解决方案之前,欧拉计画几乎总是给您提供一个示例,您可以使用该示例来检查代码:

>>> check(3797)
True

如果数字为checkFalse2或{{1},还必须在3函数中添加条件以返回5 },因为在问题中已明确指出。


结果是预期的:7

答案 1 :(得分:2)

Joe Iddon已在代码中解释了该错误,但您可以通过将gen转换为实际的生成器来加快速度。这样,您可以在检测到复合数字后立即停止检查给定nb的结果(并且gen将停止生成它们)。我还对您的素养测试仪做了一些小的调整。请记住,or运算符会短路,因此,如果aa or b中为True-ish,则不会费心计算b

def isPrime(n):
    if n in {2, 3, 5, 7}:
        return True
    if n < 2 or n%2 == 0:
        return False
    if n%3 == 0 or n%5 == 0:
        return False
    r = int(n**0.5)
    f = 5
    while f <= r:
        if n%f == 0 or n%(f+2) == 0:
            return False
        f += 6
    return True

def gen(nb):
    yield nb
    nb_str = str(nb)
    for k in range(1, len(nb_str)):
        yield int(nb_str[k:])
        yield int(nb_str[:-k])

def check(nb):
    for t in gen(nb):
        if not isPrime(t):
            return False
    return True

c = s = 0
# Don't check single digit primes
i = 11
while c < 11:
    if check(i):
        c += 1
        s += i
        print(i)
    i += 2

print('sum', s)

输出

23
37
53
73
313
317
373
797
3137
3797
739397
sum 748317  

实际上,您可以摆脱check函数,而用all代替它,它也像or一样会短路。因此,您可以替换

if check(i):

使用

if all(map(isPrime, gen(i))):