# Euler Problem 10¶

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.