Euler Problem 10

Back to overview.

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.

In [1]:
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())
61.8695481220002
142913828922

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.

In [2]:
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$.

In [3]:
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())
74.5315607270004
142913828922

Okay, I honestly did not expect this to be slower than our generator. Gotta keep that in mind for future prime related problems.