Flag variables like end
are poor style. Setting a variable so that some other code can check it and exit the loop is cumbersome. If you want to break out of the loop, just write break
.
Avoid naming variables the same as built-in functions. Pick a different name instead of all
.
Applying those two changes:
numbers = list(range(2, 2000000))
delnum = 2
while numbers.index(delnum)+1 <= len(numbers):
for x in numbers:
if x % delnum == 0 and delnum != x:
numbers.remove(x)
if numbers.index(delnum)+1 == len(numbers):
break
if numbers.index(delnum)+1 <= len(numbers):
delnum = numbers[numbers.index(delnum) + 1]
print(sum(numbers))
numbers.index(delnum) + 1 <= len(numbers)
will always be True
(or it could crash with a ValueError
, which shouldn't be possible here). So, the code is just…
numbers = list(range(2, 2000000))
for prime in numbers:
for x in numbers:
if x % prime == 0 and prime != x:
numbers.remove(x)
print(sum(numbers))
That is not only a simplification, it's also a performance improvement, since we have eliminated all of the .index()
calls (each of which involves a linear search of the list).
However, this algorithm is not the sieve-of-eratosthenes; it's much slower. In particular, the Sieve of Eratosthenes involves no division or modulo operations. It also does not involve .remove()
operations, which are slow because they involve a linear search of the list to find the element to remove, then copying all subsequent elements to fill in the hole left by the removal. Since the outer loop is O(n), the inner loop is O(n), and numbers.remove()
is O(n), this "improved" solution is still O(n3), which is very bad news when n = 2 000 000.