Problem #77 concerns partitions of numbers where the summands in each partition are composed of the prime numbers less than the number. The question reads:
Project Euler Problem 77: Prime summations
It is possible to write ten as the sum of primes in exactly five different ways:
7 + 3
5 + 5
5 + 3 + 2
3 + 3 + 2 + 2
2 + 2 + 2 + 2 + 2
What is the first value which can be written as the sum of primes in over five thousand different ways?
You may notice that this problem is very similar to Problem #31 and Problem #76. As a result, my code for solving this problem is very similar to the code for each of those problems. This code was heavily inspired by Project Euler’s documentation for Problem #31. Here is my solution:
Solution #1: Dynamic Approach
As we did in Problem #31 and Problem #76, we can notice that adding larger potential summands (or larger primes in this case) will only add recursively to the same problem with smaller summands. Thus, it suffices to work up the list of summands, dynamically counting the number of partitions for each number up to n with each of the smaller summands and then recursively counting the partitions added by the highest summand. By calculating a list of potential summands with the Sieve of Eratosthenes, this approach can be used to find the number of partitions in this problem. Unfortunately, because an upper bound is not given, solving this problem will either involve arbitrary iteration or guessing and checking. I decided to use a mixture of both by repeatedly multiplying the maximum possible prime by 3. Here is an implementation of this approach in Python 2.7:
'''
Author: Walker Kroubalkian
Dynamic Approach to Project Euler Problem #77
'''
import time
def subProblem(n,m):
numbers = sieveEratosthenes(n)
ways = [0]*(n+1)
ways[0] = 1
for i in range(len(numbers)):
for j in range(numbers[i], n+1):
ways[j] = ways[j] + ways[j-numbers[i]]
for x in range(n+1):
if(ways[x]>m):
return x
return -1
def sieveEratosthenes(n):
myPrimes = []
primePossible = [True]*(n+1)
primePossible[0] = False
primePossible[1] = False
for (i,possible) in enumerate(primePossible):
if possible:
for x in range(i*i, (n+1), i):
primePossible[x] = False
myPrimes.append(i)
return myPrimes
def projectEulerProblemSeventySeven(m):
c = 10
while(True):
a = subProblem(c, m)
if(a!=-1):
return a
c*=3
start = time.time()
print projectEulerProblemSeventySeven(5000)
print ("--- %s seconds ---" % (time.time()-start))
'''
Prints
71
--- 0.000175952911377 seconds ---
for input of m = 5000.
'''
And with that we’re done. For a small input of m = 1000, this dynamic approach managed to run in under a millisecond. It would be interesting to see if there is a more efficient solution for larger inputs.
Thanks for reading! See you tomorrow.

