问题描述
金蝉素数:
某古寺的一块石碑上依稀刻有一些神秘的自然数。 专家研究发现:这些数是由1,3,5,7,9这5个奇数字排列组成的5位素数,同时去掉它的最高位与最低位数字后的3位数还是素数,同时去掉它的高二位与低二位数字后的一位数还是素数。因此人们把这些神秘的素数称为金蝉素数,喻意金蝉脱壳之后仍为美丽的金蝉。
试求出石碑上的金蝉素数
问题分析
- 首先构造一个判断素数的函数,之前做过
- 如何生成只含有13579的五位数,要写出所有排列,难点
- 要生成去掉前后各一位后剩下的三位数,这个之前做过,reduce(lambda x,y:x*10+y, list[1:4])
代码
#构造一个判断素数的函数
def sushu(n):
a=0
for k in range(2,n):
if n%k==0:
a+=1
if a==0:
return True
c=[1,3,5,7,9]
def chachao(x):
for i in range(10000,x): #没想到如何直接生成这样的五位数,所以遍历所有的五位数,用排除法
l=0
if sushu(i):
for j in str(i):
if (int(j) not in c): #判断 j 是否在五个数内,排除不是由这五个数组成的数
l+=1
if l==0:
b=[int(j) for j in str(i)] #但生成的数会有11357等这样重复的数字,仍不符合要求
if len(b)==len(set(b)): #用一个set函数,生成不重复数组,排除掉11357这样重复的数字
m=reduce(lambda x, y: x*10+y, b[1:4]) #生成剩下的三位数
if sushu(m):
print i
chachao(99999)
#结果
13597
15937
51973
53791
57193 #中间位为1,不符合要求
75931
79531
91573
95713
上面的结果虽然写出来了,但有几个缺点:
- 素数判断函数,只需遍历到该数的平方根即可(2,sqrt.(n)+1)
- 数的生成方法用了排除法,需要遍历所有的五位数然后找到符合的,导致运行速度超级慢;
- 没有考虑去掉前后各两位而剩下一位数的情况,即1在中位的情况,1不是素数
别人家的超简洁代码
def isPrimeNum(n):
for k in range(2, int(math.sqrt(n) + 1)): #取值范围缩小到平方根+1,可以节省时间
if n % k == 0:
return False
return True
from itertools import permutations
for p in permutations([1,3,5,7,9], 5): #惊叹不已!利用permutation函数,直接生成符合条件的五位数,简单直接
for l in (p[1:-1], p[::2], p): #切片的运用,又和for循环结合,方便快捷,
s = reduce(lambda x, y: 10 * x + y, l)
if not isPrimeNum(s):
break
else:
print p
看完后就是羡慕,这么简洁的代码,何时能写出来,好多条件目前自己是不具备的:
- 对python基础函数的了解,需要积累,此题中比如切片、permutations函数事半功倍
- 对语言结构的巧妙布置,此题中 for循环与三个切片的结合就省了好多行
知识积累:
-
切片
p[::2] 是从头开始,每隔两个元素取一次
p[:10:2] 前十个元素,每个两个取一次 -
迭代器的使用 from itertools import permutations
permutations([p],r);返回p中任意取r个元素做排列的元组的迭代器
combinations(iterable,r);创建一个迭代器,返回iterable中所有长度为r的子序列,返回的子序列中的项按输入iterable中的顺序排序,不重复
其他迭代器函数:
https://blog.csdn.net/neweastsun/article/details/51965226
参考资料:
https://blog.csdn.net/u010019717/article/details/51450965#3-金蝉素数-中