Speeding up a script -- looking for ideas

Tim Peters tim.one at comcast.net
Sun Oct 20 15:51:31 EDT 2002


[Richard Bow]
> I'm hoping to get some hints for significantly speeding up the below
> script. I've found 43 integers between 1 and 1,000,000 that satisfy the
> condition, and would like to push on toward 10,000,000 in hopes
> of finding an integer for which there are 3 pairs. Of course, another
> reason for asking is to learn more Python from you guys.

I'm going to cheat by using a better algorithm.  This finds all the results
up to 10,000,000 in about half a second on my box (under current CVS Python,
which is a bit zippier).  You'll find going up to 100,000,000 more
interesting (which takes longer than an eyeblink, but a lot less time than
it's taking me to add this gratuitous parenthetical comment <wink>).

The key gimmick:  The cube root of N is a *hell* of a lot smaller than N.
So rather than look at each N and then look for all ways of expressing N as
the sum of two cubes, instead loop over all cubes and figure out all the N
that can be gotten via adding two cubes.

This is Rule #1 of Python optimization:

    Any Python program using a dict is 1000x faster than any C program.

There are no exceptions to this rule <ahem>.


def drive(start, end):
    largest_root = int(end ** 0.333)
    while (largest_root + 1) ** 3 < end:
        largest_root += 1

    cubes = [i**3 for i in xrange(1, largest_root + 1)]
    ncubes = len(cubes)

    n2cubes = {}  # map n to list of (cube1, cube2)
    for i in xrange(ncubes):
        cube1 = cubes[i]
        for j in xrange(i, ncubes):
            cube2 = cubes[j]
            n = cube1 + cube2
            if n > end:
                break
            n2cubes.setdefault(n, []).append((cube1, cube2))

    for n, pairs in n2cubes.iteritems():
        if len(pairs) >= 2:
            print n, pairs





More information about the Python-list mailing list