Project Euler 37 要求找到前 1000 个数字中所有截断后仍为素数的素数。截断后仍为素数的素数是指,从该素数的左边或右边截掉任意位数字后,剩余的数字仍然是素数。
为了解决这个问题,需要实现两个函数:left_truncable 和 right_truncable,分别用于查找截断后仍为素数的左截断素数和右截断素数。
解决方案
首先,定义一个函数 is_prime 来判断一个数字是否为素数。
def is_prime(n):
i = 2
while i<n:
if(n%i == 0):
return False
i+=1
return True
然后,定义函数 left_truncable 来查找截断后仍为素数的左截断素数。
def left_truncable(num):
li = []
x = str(num)
if(is_prime(num)):
n = len(x)
check = ""
i = 1
while(i<n):
if(is_prime(int(x[i:]))):
check = "True"
i+=1
else:
check = "False"
break
if(check == "True"):
li.append(num)
return li
这个函数首先将数字转换为字符串,然后从左到右逐位截断,并检查每个截断后的数字是否为素数。如果所有截断后的数字都是素数,则将该数字添加到列表 li 中。
接下来,定义函数 right_truncable 来查找截断后仍为素数的右截断素数。
def right_truncable(num1):
ri = []
x1 = str(num1)
if(is_prime(num1)):
n = len(x1)
check = ""
j = 1
while(j<n):
if(is_prime(int(x1[:j]))):
check = "True"
j+=1
else:
check = "False"
break
if(check == "True"):
ri.append(num1)
return ri
这个函数也首先将数字转换为字符串,然后从右到左逐位截断,并检查每个截断后的数字是否为素数。如果所有截断后的数字都是素数,则将该数字添加到列表 ri 中。
最后,使用交集运算符 & 找出两个列表 li 和 ri 的公共元素,这些公共元素就是截断后仍为素数的素数。
print common_elements(right, left)
代码例子
以下代码给出了该问题的完整解决方案:
def is_prime(n):
i = 2
while i<n:
if(n%i == 0):
return False
i+=1
return True
def left_truncable(num):
li = []
x = str(num)
if(is_prime(num)):
n = len(x)
check = ""
i = 1
while(i<n):
if(is_prime(int(x[i:]))):
check = "True"
i+=1
else:
check = "False"
break
if(check == "True"):
li.append(num)
return li
def right_truncable(num1):
ri = []
x1 = str(num1)
if(is_prime(num1)):
n = len(x1)
check = ""
j = 1
while(j<n):
if(is_prime(int(x1[:j]))):
check = "True"
j+=1
else:
check = "False"
break
if(check == "True"):
ri.append(num1)
return ri
def common_elements(list1, list2):
return [element for element in list1 if element in list2]
right = []
for e in range(1, 1000):
r = right_truncable(e)
if(r != []):
right.append(r)
left = []
for f in range(1, 1000):
l = left_truncable(f)
if(l != []):
left.append(l)
print common_elements(right, left)
运行以上代码,可以得到前 1000 个数字中所有截断后仍为素数的素数,即 [137, 313, 317, 373, 379, 797]。