Search code examples
pythonnumber-theory

Project Euler #23 Optimization


Non-abundant sums

Problem 23

A number n is called abundant if the sum of its proper divisors exceeds n. Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.

I have tried several things and optimized my code as much as I could with my limited knowledge of coding. A few days ago I started learning how to code, and I found this page, (project euler), I deviated a little from learning and just started to code to try and solve the problems. So far I've managed to solve most of the easiest problems without taking a long time, but this one is taking too long in comparison. Sorry if my code isn't understandable.

sum_abundant = []
for i in abundant:
    for n in abundant:
        c = i + n
        if n > i:
            break
        if c < 28123:
            if c not in sum_abundant:  # if the number has already been removed, it won't remove it again.
                sum_abundant.append(c)

("abundant" is a list with all the abundant numbers.) It isn't the whole code, just the part where I believe it takes most of the time.


Solution

  • One approach that you could take is to decompose the problem into intermediate steps:

    • Determine the proper divisors of all numbers up to 28123
    • Select the numbers that are "abundant" using the lists of divisors
    • Find all pairs of abundant numbers and flag their sums
    • Select the numbers that were not flagged by the previous steps (those will be the numbers that cannot be expressed as the sum of two abundants)
    • Compute the sum of this result

    here's an example:

    # Create a list of proper divisora for all numbers up to 28123...
    
    properDivs     = [ [] for _ in range(28124) ] 
    for n in range(1,28124):
        for i in range(2*n,28124,n):
            properDivs[i].append(n)
    
    # Select the numbers that are abundant (sum of divisors > number itself)...
    
    abundants = [n for n,divs in enumerate(properDivs) if sum(divs)>n]
    
    # Find all pairs of abundant numbers and flag their sums
    
    from itertools import combinations_with_replacement
    sumOf2Abundants = [False for _ in range(28124)]
    for a,b in combinations_with_replacement(abundants,2):
        if a+b<len(sumOf2Abundants):
            sumOf2Abundants[a+b] = True
    
    # Select numbers that were not flagged...
    
    result = [n for n,isSumOf2 in enumerate(sumOf2Abundants) if not isSumOf2]
    
    # compute and print the sum of the above result
    
    print(sum(result))