我试图解决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)
我怀疑错误来自结果列表
答案 0 :(得分:3)
是的,由于切片已关闭,gen()
函数无法正常工作,另外,您将2
,3
,5
和7
计为问题被拒绝的截断素数。
第二个切片应该相反:
>>> 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
如果数字为check
,False
,2
或{{1},还必须在3
函数中添加条件以返回5
},因为在问题中已明确指出。
结果是预期的:7
。
答案 1 :(得分:2)
Joe Iddon已在代码中解释了该错误,但您可以通过将gen
转换为实际的生成器来加快速度。这样,您可以在检测到复合数字后立即停止检查给定nb
的结果(并且gen
将停止生成它们)。我还对您的素养测试仪做了一些小的调整。请记住,or
运算符会短路,因此,如果a
在a 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))):