问题
Is there any suggestion on solving next higher prime and palindrome number from a given int.
Here is the snippet I am trying but its a kind of slow, please suggest if you ve any good algorithm that i can test.
#!/usr/bin/python
def next_higher(n):
while True:
s = str(n)
if not any([n % i == 0 \
for i in range(2, int(n**0.5))]) and s == s[::-1]:
return n
n = n + 1
print next_higher(2004)
print next_higher(20)
Output:
10201
101
Updated code testing for palindrome before prime. much faster than my previous code. I am implementing the suggestion from user2357112.
#!/usr/bin/python
def next_higher(n):
while True:
s = str(n)
if s == s[::-1]:
if not any([n % i == 0 \
for i in range(2, int(n**0.5))]):
return n
n = n + 1
print next_higher(2004111)
print next_higher(2004)
print next_higher(2004)
print next_higher(20)
回答1:
There are quite a few optimizations you could do:
- Like user2357.. suggested in the comments, test palindromeness first, and then check if the number is prime, since prime check is more expensive.
- You don't need to check even number divisibility once you check is the number is divisible by 2. So you can change it to
[2] + range(3, int(n**0.5) + 1, 2)
to check only odd numbers after 2. (Also you need to do sqrt + 1 like I mentioned in the comments) - You should use
()
instead of[]
.[]
generates the entire list of factors first and only then checks forany
. If you use()
, it creates a generator, so it stops as soon as aTrue
value is found without calculating the entire list. - You should also use
xrange
instead ofrange
for the same reason (xrange
gives a generator,range
gives a list) - You can use the Sieve of Eratosthenes algorithm to significantly reduce the time taken for prime number check.
- You can also see if the palindrome check can be made faster. You can actually skip a whole lot of numbers instead of doing just
+ 1
each time.
Here is a version with most of these optimizations except the last two:
def next_higher(n):
if n % 2 == 0:
n = n - 1
while True:
n = n + 2
s = str(n)
if s == s[::-1]:
if not any((n % i == 0 for i in xrange(3, int(n**0.5) + 1, 2))):
return n
This should be pretty fast for your needs I believe. But you can do the last 2 optimizations to make it much more faster if you want.
回答2:
Other than what has already been suggested,
What I suggest is that you first get the first palindrome number that is just higher than the given integer.
You can do this by trying to match the centre digits outwards.
Also, you should only check for numbers with odd number of digits, since if a number has even number of digits and it is a palindrome, then it will always be divisible by 11 and cannot be prime.
Once you get the first palindrome number that has odd number of digits and that is just higher than the current number, test it for primality and find the next palindrome number higher than this one.
You can do this by incrementing the centre digit.
Keep doing this till it rolls over to zero. In that case start incrementing the two neighbouring digits.
Continue, till you reach a prime number.
回答3:
I tried optimizing the palindrome check i.e to find odd palindrome's. Since the first digit should be odd number, i focused on that part. Here's the code below with the assumptions its greater than 1 digit.
def next_odd_palindrome(n):
"""to check the next odd palindrome number"""
if n%2==0:
n=n-1
while True:
n=n+2
s = str(n)
if int(s[0])%2==0:
n = int(str(int(s[0])+1)+ s[1:])
s = str(n)
if s==s[::-1]:
return n
let me know if anything wrong.
回答4:
Just for the fun of it, I implemented all optimizations by Hari Shankar and Abhishek Bansal.
It first finds the higher odd length palindrome, then increment the palindrome in a way that keeps its palindromity. Then checks each number using prime numbers calculated by Sieve method in the beginning.
This can process up to n=10^14
(can be higher if you increase the CACHE size) under 1 second in my computer =D
primes = []
CACHE = int(10**7) # Cache size for Sieve
# Custom class for immediate printing of output
import sys
class Unbuf:
def __init__(self,stream):
self.stream = stream
def write(self,data):
self.stream.write(data)
self.stream.flush()
sys.stdout = Unbuf(sys.stdout)
def sieve():
global primes
is_prime = [False,False]+([True]*(CACHE-1))
for i in xrange(2,int(CACHE**0.5)):
if is_prime[i]:
is_prime[i*i::i] = [False]*((CACHE-i*i+i)/i)
primes = [num for num, bool_prime in enumerate(is_prime) if bool_prime]
def is_prime(n):
"""Checks whether n is prime"""
global primes
if n<2:
return False
if n==2:
return True
for prime in primes:
if prime>n**0.5+1:
return True
if n%prime==0:
return False
# For the case that the number is bigger than the square of our largest prime
for num in xrange(primes[-1]+2,n**0.5+1,2):
if n%num==0:
return False
return True
def next_higher_odd_length_palindrome(n):
n = str(n)
if len(n)%2==0: # Even length, take the smallest odd length (10(00)*1)
n = '1'+('0'*(len(n)-1))+'1'
else:
middle_idx = len(n)/2
left = int(n[:middle_idx+1])
left_cmp = n[middle_idx::-1]
right_cmp = n[middle_idx:]
# If mirroring left part to right part
# makes the number smaller or equal, then
if right_cmp>=left_cmp:
# Increase the left half number
left = left+1
# Mirror left part to the right part
n = str(left)+str(left)[-2::-1]
return n
def next_higher(n):
if n<=1:
return 2
# Ensure the number is a palindrome of odd length
n = next_higher_odd_length_palindrome(n)
while True:
if is_prime(int(n)):
return int(n)
n = next_higher_odd_length_palindrome(n)
if int(n[0])%2==0:
new_lead = str(int(n[0])+1)
n = new_lead+n[1:-1]+new_lead
import time
print 'Sieving...',
start_time = time.time()
sieve()
print 'Done in %.3fs' % (time.time() - start_time)
print next_higher(2004111)
print next_higher(2004)
print next_higher(20)
while True:
n = int(raw_input('Enter n: '))
start_time = time.time()
result = next_higher(n)
print 'Next higher prime palindrome: %d (calculated in %.3fs)' % (result, time.time() - start_time)
Which in my computer gives this output:
Sieving... Done in 1.444s 3007003 10301 101 Enter n: 1999999999 Next higher prime palindrome: 10000500001 (calculated in 0.004s) Enter n: 1999999999999 Next higher prime palindrome: 3000002000003 (calculated in 0.051s) Enter n: 1000000000000 Next higher prime palindrome: 1000008000001 (calculated in 0.030s) Enter n:
来源:https://stackoverflow.com/questions/20650623/next-higher-prime-and-palindrome-number