First of all, although it will not change the order of your time-complexity, you can still narrow down the list of numbers that you are checking by a factor of 6, since you only need to check numbers that are either equal to 1 mod 12
or equal to 5 mod 12
(such as [1,5], [13,17], [25,29], [37,41], etc).
Since you only need to count the primes which are sum of squares of two numbers, the order doesn't matter. Therefore, you can change range(a,b+1)
to range(1,b+1,12)+range(5,b+1,12)
.
Obviously, you can then remove the if n % 2 == 0 and n > 2
condition in function is_prime
, and in addition, change the if is_prime(i) and (i-1)%4 == 0
condition to if is_prime(i)
.
And finally, you can check the primality of each number by dividing it only with numbers that are adjacent to multiples of 6 (such as [5,7], [11,13], [17,19], [23,25], etc).
So you can change this:
range(3,int(math.sqrt(n))+1,2)
To this:
range(5,math.sqrt(n))+1,6)+range(7,math.sqrt(n))+1,6)
And you might as well calculate math.sqrt(n))+1
beforehand.
To summarize all this, here is how you can improve the overall performance of your program:
import math
def is_prime(n):
max = int(math.sqrt(n))+1
return all(n % i for i in range(5,max,6)+range(7,max,6))
count = 0
b = int(raw_input())
for i in range(1,b+1,12)+range(5,b+1,12):
if is_prime(i):
count += 1
print count
Please note that 1
is typically not regarded as prime, so you might want to print count-1
instead. On the other hand, 2
is not equal to 1 mod 4
, yet it is the sum of two squares, so you may leave it as is...