1

I am trying to solve the 10 problem in the Project Euler. It consists on finding the sum of all the primes below two million. I wrote the following code based on the Sieve of Eratosthenes.

import time
t0 = time.time()
n=200000
liste=list(range(2,n))
k=2
s=2
while k <=n:
    liste=list(set(liste)-set(range(k,n,k)))
    if liste!=[]:
        k=min(liste)
        s+=k
    else:
        break
print(s)
t1 = time.time()
total = t1-t0
print(total)

I tested the above code for n=200000, but it is too slow for n=2000000. I would be very thankful to get any help to improve this program.

Will Ness
  • 62,652
  • 8
  • 86
  • 167
  • http://stackoverflow.com/a/23423821/2141635 use sum and you have the answer – Padraic Cunningham Jun 17 '15 at 10:04
  • 1
    Also related: http://stackoverflow.com/q/2068372/1639625 – tobias_k Jun 17 '15 at 10:06
  • 1
    related: [Speed up bitstring/bit operations in Python?](http://stackoverflow.com/q/2897297/4279) – jfs Jun 17 '15 at 16:38
  • just replace `while k <=n` with `while k <=(n/k)` and be done with it (of course, now you end up with non-empty `liste`, which will contain only primes at this point!). – Will Ness Jun 19 '15 at 12:53
  • @will Ness Thanks, it works, it is much faster than mine. However it still too slow for $n=2000000$. – Driss Alami Jun 22 '15 at 10:50
  • @DrissAlami: what does it mean "too slow" (use number of milliseconds on your hardware)? What functions did you try from [this answer](http://stackoverflow.com/a/2068548/4279)? – jfs Jun 22 '15 at 13:25
  • I've retracted my close vote (working code, belongs on Code Review). The code was _so_ slow, it was functionally _not_ working, I thought. – Will Ness Jun 23 '15 at 10:19

2 Answers2

0

For finding the sum of prime numbers below 200000, the code below(using sieve of eratosthenes), works much faster, Your code takes nearly 55secs, whereas the code below takes just 0.8secs to execute!

import time
t0 = time.time()
n = 200000
sieve = [True] * (n + 1)
for i in range(2, n + 1) :
  if sieve[i] :
     for mult in range(i + i, n + 1, i) :
        sieve[mult] = False
s=0     
for i in range(2,n + 1):
    if sieve[i] :
        s+=i    
print(s)
t1 = time.time()
total = t1-t0
print(total)
Sanjana S
  • 131
  • 1
  • 1
  • 6
0

Always try to measure empirical complexity of your code at several ranges.

Your code is slow because of how you find the set difference, and that you always convert between set and list and back. You should be using one set throughout, and updating it in place with

    sete.difference_update(range(p*p,n,p*2))

To find the min element, you can just call min(sete) on the set, no list conversion required.

Because of the inefficient search for the min element the overall complexity of the resulting code will be nearing n^1.5, which is not too bright, but not too terrible either. In particular, it finishes in under 4.9 seconds on ideone.com, finding the sum for the primes below 2000000, and 0.5 seconds for 400000 (with the additional optimization of working with odds only, in the first place).

Will Ness
  • 62,652
  • 8
  • 86
  • 167