The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
Okay, reuse prime generator from 7 and go.
import timeit
def is_prime(n, smaller_primes):
for s in smaller_primes:
if n % s == 0:
return False
if s * s > n:
return True
return True
def prime_generator_function():
primes = [2, 3, 5, 7]
for p in primes:
yield p
while True:
p += 2
if is_prime(p, primes):
primes.append(p)
yield p
def brute_force():
ps = prime_generator_function()
s = 0
p = next(ps)
while p < 2000000:
s += p
p = next(ps)
return s
print(timeit.timeit(brute_force, number=10))
assert(brute_force() == 142913828922)
print(brute_force())
Okay, here it may actually be way smarter to use a sieve. We implent it because the old one was shitty. Okay, I am actually interested in the time difference. So we use the old one first and then implement the optimization.
def get_primes_smaller(number):
primes = []
prospects = [n for n in range(2, number)]
while prospects:
p = prospects[0]
prospects = [x for x in prospects if x % p != 0]
primes.append(p)
return primes
def brute_force():
return sum(get_primes_smaller(2000000))
#print(timeit.timeit(brute_force, number=1))
#print(brute_force())
This did not even terminate. We optimize the sieve by stopping when $p^2 > number$.
def sieve_of_eratosthenes(number):
primes = []
prospects = [n for n in range(2, number)]
while prospects:
p = prospects[0]
prospects = [x for x in prospects if x % p != 0]
primes.append(p)
if p * p > number:
break
return primes + prospects
def brute_force():
return sum(sieve_of_eratosthenes(2000000))
assert(sieve_of_eratosthenes(10) == [2, 3, 5, 7,])
print(timeit.timeit(brute_force, number=10))
assert(brute_force() == 142913828922)
print(brute_force())
Okay, I honestly did not expect this to be slower than our generator. Gotta keep that in mind for future prime related problems.