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: