No_35Circular primes

题目:

The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.

There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.

How many circular primes are there below one million?

代码为:
#coding=utf-8
import itertools,math,time
def isprime(n):
    if not  n%2:
        return False
    for x in xrange(3,min(int(math.sqrt(n))+1,n),2):
        if not n%x:
            return False
    return True
def issuit(n):
    nlist=getallnum(n)
    for num in nlist:
        if not isprime(num):
            return -1,nlist

    return 0,nlist
def getallnum(n):
    n_str=str(n)
    relist=set()
    for index in xrange(len(n_str)):
        relist.add(int(n_str[index:]+n_str[:index]))
    return relist
t=time.time()
maxvalue=1000000
reset=set([2])#结果集合
parelist=[-1]*maxvalue#-1表示未读

for num in xrange(3,maxvalue,2):
    if parelist[num]==-1:
        success,sortset=-2,set([num])
        if isprime(num):
            success,sortset=issuit(num)#是否是质数,返回的列表
            if success==0:
                reset.update(sortset)
        for  tempnum in sortset:#把所有数据元素的数字的倍数置为已读
            if tempnum<num:
                continue
            for x in xrange(tempnum,maxvalue,2*tempnum):
                if parelist[x]==-1:
                    parelist[x]=1

print reset
print len(reset)
print time.time()-t
运行结果为:
set([7937, 2, 3, 999331, 5, 7, 1931, 13, 17, 131, 919, 919393, 31, 9377, 11939, 37, 113, 93719, 1193, 71, 331999, 3119, 99371, 933199, 311, 391939, 91193, 9311, 19391, 11, 197, 199, 73, 971, 39119, 337, 37199, 19937, 3779, 93911, 939193, 79, 733, 719, 991, 97, 993319, 199933, 7793, 193939, 373, 319993, 393919, 71993, 939391])
55

2.36299991608

缺点:
太慢了了,
牛人的代码为:

import math,time
t=time.time()

#sieve method for getting list of primes.
def getprimes(n):
	if n==2: return [2]
	elif n<2: return []
	s=range(3,n+1,2)
	mroot = n ** 0.5
	half=(n+1)/2-1
	i=0;m=3
	while m <= mroot:
		if s[i]:
			j=(m*m-3)/2;s[j]=0
			while j<half:
				s[j]=0;j+=m
		i=i+1;m=2*i+3
	return [2]+[x for x in s if x]

# filter bad primes
goodNums=set(['1','3','7','9'])
good_filter=lambda x: not set(str(x)).difference(goodNums)
primes=filter(good_filter,getprimes(1000000))
def rotate(n_str):
    return n_str[-1]+n_str[:-1]
def isCircullar(n_str):
    global primes
    for i in range(len(n_str)-1):
        n_str=rotate(n_str)
        if not int(n_str) in primes:
            return 0
    return 1

circullarCounter=lambda x,y:x+isCircullar(str(y))

#explicitly include 2 and 5 to circullar primes (excluded at filtering procedure)
print reduce(circullarCounter,primes,2)
print time.time()-t
运行结果为
55
0.297000169754

呃呃。。才0.2秒,我了个去。。比我快10倍啊。。都不知道是多少个数量级了。艹 了。
看了别人的改了的:

#coding=utf-8
import math,time
t=time.time()
def isprime(n):#判断是不是素数
    if n==2:
        return True
    else:
        for x in xrange(3,int(math.sqrt(n))+1,2):
            if not n%x:
                return False
        return True
def geprime(n):#其实是获取所有奇数
    relist=[2]
    sourceclist=[-1]*n
    for num in xrange(3,n,2):
        if sourceclist[num]==1:
            continue
        for tempnum in xrange(num,n,2*num):
            sourceclist[tempnum]=1
        relist.append(num)
    return relist
def getloop(n):
    reset=set()
    n_str=str(n)
    temp_str=n_str
    for i in range(len(n_str)):
        temp_str=temp_str[-1]+temp_str[:-1]
        reset.add(temp_str)
    return { int(numstr) for numstr in reset}

goodnumlist=['1','3','7','9']
onesteplist=geprime(1000000)
#print onesteplist
b=lambda x: not set(str(x)).difference(goodnumlist)
goodprimelist=filter(b,set(onesteplist))
#print goodprimelist
#comparedict=dict.fromkeys(goodprimelist,0)
primeset=set()
print time.time()-t
for key in goodprimelist:
    if not key in primeset:
        tempset=getloop(key)
        tempsuccess=True
        for tempnum in tempset:
            if tempsuccess==True and  tempnum not in   goodprimelist:
                tempsuccess=False
                break
            #comparedict[tempnum]=1
        if tempsuccess==True:
            primeset.update(tempset)
print len(filter(lambda x:isprime(x),primeset))+2#里面不包含2,5,所以计数的时候要+2
print time.time()-t
运行结果为:
0.3140001297
55

0.360000133514

呃呃。。。慢了快1/2了。艹 了。。。
等下再研究下为什么会这个样子呃呃。。。
终于把速度提升上去了。
耗时最多的是getprimes()那里。
有两点体会:
1.有时候顺序很重要,像这里的我把isprime()这种比较耗时,移到最后。总时间就会大大减少

2.sourcelist牛人的数据结构真的很重要。。用了他的速度就上去了。
代码为:

__author__ = 'Administrator'
import math,time
t=time.time()

#sieve method for getting list of primes.
def getprimes(n):
	if n==2: return [2]
	elif n<2: return []
	s=range(3,n+1,2)
	mroot = n ** 0.5
	half=(n+1)/2-1
	i=0;m=3
	while m <= mroot:
		if s[i]:
			j=(m*m-3)/2;s[j]=0
			while j<half:
				s[j]=0;j+=m
		i=i+1;m=2*i+3
	return [2]+[x for x in s if x]
# filter bad primes
goodNums=set(['1','3','7','9'])
good_filter=lambda x: not set(str(x)).difference(goodNums)
#print sorted(list(getprimes(1000000)))
primes=filter(good_filter,getprimes(1000000))
print time.time()-t
def rotate(n_str):
    return n_str[-1]+n_str[:-1]
def isCircullar(n_str):
    global primes
    for i in range(len(n_str)-1):
        n_str=rotate(n_str)
        if not int(n_str) in primes:
            return 0
    return 1

circullarCounter=lambda x,y:x+isCircullar(str(y))

#explicitly include 2 and 5 to circullar primes (excluded at filtering procedure)
print reduce(circullarCounter,primes,2)
print time.time()-t
结果:
55
0.302999973297

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值