4
\$\begingroup\$

The code below takes integer n as input, and delivers a list of all primes up to integer n using the Sieve of Eratosthenes.

My question is, could you please help me optimize this code? Is it considered poor code to use 'try' flow control? I'd like to optimize the code such that I don't need it.

def factorfinder(n):
    A = range(0,n+1)
    for i in xrange(0,int(math.sqrt(n))):
        if i == 0 or i == 1:
            A[i] = 0
            continue
        for j in xrange(0,n):
            try:
                A[i**2+j*i] = 0
            except IndexError:
                pass
    return filter(lambda x: x != 0, A)
\$\endgroup\$
2
  • \$\begingroup\$ Another optimization you can do. Beyond initial conditions (i.e. 1,2,3), primes are only found at i = 6k-1 or i = 6k+1. See: primes.utm.edu/notes/faq/six.html So, you only need test 5,7,11,13,17,19,23,25,29,31,... \$\endgroup\$ Commented Apr 23, 2016 at 20:45
  • \$\begingroup\$ This is not going to work for 25, you should use int(math.sqrt(n))+1. \$\endgroup\$ Commented Apr 24, 2016 at 7:41

1 Answer 1

3
\$\begingroup\$

Your if statement can be moved out of the loop, if you do you need to change the range to start at 2.

A[0] = 0
A[1] = 0
for i in xrange(2, int(math.sqrt(n))):

For your other loop, we can think of the algorithm slightly differently. You start at i ** 2, you take a step of i, and it ends on len(A) (shown by the try-except). Or:

for j in xrange(i ** 2, n + 1, i):

As for filter you can change it to use bool or None instead of the lambda. Alternately you can change it to a list comprehension:

return [i for i in A if i != 0]

This makes the code simple:

def factorfinder(n):
    A = range(n + 1)
    A[0] = 0
    A[1] = 0
    for i in xrange(2, int(math.sqrt(n))):
        for j in xrange(i ** 2, n + 1, i):
            A[j] = 0
    return filter(bool, A)
\$\endgroup\$
5
  • \$\begingroup\$ Thanks Joe for the supremely helpful advice. I'm already applying it to another similar problem I'm working on. \$\endgroup\$
    – baverso
    Commented Apr 23, 2016 at 17:05
  • \$\begingroup\$ You could use filter(bool, A) instead of filter(lambda x: x != 0, A) \$\endgroup\$
    – zondo
    Commented Apr 23, 2016 at 17:12
  • \$\begingroup\$ @zondo Yes you could, I'll edit that in a bit \$\endgroup\$
    – Peilonrayz
    Commented Apr 23, 2016 at 17:15
  • 1
    \$\begingroup\$ @zondo, @JoeWallis: or just filter(None, A) which does the same. \$\endgroup\$ Commented Apr 24, 2016 at 9:10
  • \$\begingroup\$ @SjoerdJobPostmus I didn't know that, but IIRC Guido doesn't like map, filter and reduce and so wanted to remove them in Py3, so using a comprehension is probably better/safer. \$\endgroup\$
    – Peilonrayz
    Commented Apr 24, 2016 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.