## Euler’s Sum Of Powers Conjecture

### April 17, 2015

Fermat’s Last Theorem, which dates to the seventeenth century states that there are no solutions in integers to the equation xn + yn = zn for n > 2; the Theorem was finally proved a few years ago by Andres Wiles. In the eighteenth century, Euler conjectured that for any n > 2, it would take at least n terms of the form xin to sum to an n th power. That conjecture held until the age of computers, in 1967, when Lander and Parkin found the counter-example 275 + 845 + 1105 + 1335 = 1445.

Your task is to write a program that finds counter-examples to Euler’s Conjecture. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

### 7 Responses to “Euler’s Sum Of Powers Conjecture”

1. Paul said

In Python. I could not find anything clever.

```from time import clock
from itertools import combinations

def check(n, limit, first=2):
"""limitation: all terms must be different"""
pown = [i ** n for i in range(1, limit)]
pvals = set(pown)
for n_terms in range(first, n):
for p in combinations(pown, n_terms):
if sum(p) in pvals:
print p, clock() - start

def check5(limit):
pown = [i ** 5 for i in range(limit)]
pvals = set(pown)
for i, pi in enumerate(pown[1:], 1):
for j, pj in enumerate(pown[i:],i):
for k, pk in enumerate(pown[j:],j):
for l, pl in enumerate(pown[k:],k):
if pi+pj+pk+pl in pvals:
print i,j,k,l, clock() - start

start = clock()
check(5, 145) # time=4.85 secs
start = clock()
check5(145)   # time=3.44 secs
#Processor	Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz, 2001 MHz, 4 core
```
2. Paul said

A much faster method from the Lander and Parkin paper. The answer comes in a flash. I feel this can be improved, but this is already much faster.

```from __future__ import division

from time import clock
from bisect import bisect

def decompose(k, t, n):
pown = [i ** 5 for i in range(t)]
pvals = set(pown)
def find(k, t, n, data):
t5 = bisect(pown, t) - 1
tn5 = bisect(pown, t/n) - 1
if n == 2:
for v in range(tn5, t5+1):
if data and v > data[-1]:
continue
w = t - pown[v]
w5 = bisect(pown, w) - 1
if pown[w5] + pown[v] == t:
print "--", data, v, w5
else:
for s in range(t5, tn5 - 1, -1):
u = t - pown[s]
if data and data[-1] < s:
continue
find(k, u, n - 1, data + [s])
find(5, t ** 5, n, [])

start = clock()
for i in range(5, 145):
decompose(5, i, 4)
```
3. programmingpraxis said

@Paul: Please provide a citation to the paper.

4. Paul said

@ programmingpraxis: the paper: Lander and Parkin
I made a straightforward implementation. I feel it can be speeded up more. I did not use the bit at the bottom of page 101 with the mod 30 stuff.

5. Paul said

Another version in Python. It only produces “primitive” solutions, where the terms do not have a common factor. It produces the 2 tables from the Lander and Parkin paper. Also an example from Wikipedia for k=7 is found after a long time (about 40 minutes).

```from __future__ import division

from time import clock
from bisect import bisect_left, bisect_right
from fractions import gcd

def is_primitive(data):
"""if data is primitive, there is no common factor between all items"""
it = iter(data)
g = next(it, None)
if g:
for i in it:
g = gcd(g, i)
if g == 1:
return True
return False

def decompose_until(k, t, n, first=1):
""" decompose all numbers up to t as the sum of at most n terms of the form i ** k
"""
pown = [i ** k for i in range(t)]
pvals = set(pown)
L = len(pown)
def smin(target, n, hi=L):
"""returns the index in pown such that index ** k  > target // n
"""
t = target // n
return bisect_right(pown, t, hi=hi)
def smax(target, n, hi=L):
"""returns the index in pown such that index ** k  < target
if target is in pown then the index in pown is the returned index + 1
"""
return bisect_left(pown, target, hi=hi) - 1
def decompose(k, t, n):
"""decompose t**k as sum of terms of the form i ** k"""
tsafe = t
t = t ** k
Q = [(t - pown[s], n-1, [s]) for s in range(smin(t, n), smax(t, n)+1)]
while Q:
t, n, data = Q.pop()
smx = smax(t, n, data[-1]+1) + 1
if t in pvals and smx < data[-1] and is_primitive(data + [smx]):
assert sum(pown[i] for i in (data + [smx])) == tsafe ** k, "{:d} {:s}".format(tsafe, str(data+ [smx]))
print "**", tsafe, data + [smx], clock() - start
continue
smn = smin(t, n, data[-1]+1)
if n == 2:
for v in range(smn, smx + 1):
if v > data[-1]: continue
w = t - pown[v]
if w in pvals:
w5 = smax(w, n, data[-1]+1) + 1
if w5 <= v and is_primitive(data + [v, w5]):
assert sum(pown[i] for i in (data + [v, w5])) == tsafe ** k, "{:d} {:s}".format(tsafe, str(data+ [v, w5]))
print "--", tsafe, data + [v, w5], clock() - start
else:
for s in range(smx, smn - 1, -1):
if s > data[-1]: continue
Q.append((t - pown[s], n-1, data + [s]))
start = clock()
for i in range(first, t):
decompose(k, i, n)

decompose_until(5, 250, 4, first=1)
"""
k = 7 (Example wikipedia - takes long time - started @ 568
-- 568 [525, 439, 430, 413, 266, 258, 127] 2378.10256164 k=7
k = 5, n = 6 (Tabel 1 from Lander and Parkin)
-- 12 [11, 9, 7, 6, 5, 4] 0.361283899936
-- 30 [29, 19, 16, 11, 10, 5] 0.404110327133
-- 32 [28, 24, 22, 17, 16, 15] 0.430216805645
-- 67 [66, 34, 31, 29, 20, 7] 1.22579653624
-- 67 [66, 36, 31, 23, 18, 13] 1.24291212316
** 72 [67, 47, 46, 43, 19] 1.58158665811
-- 78 [64, 61, 58, 48, 35, 22] 2.25165772931
** 94 [84, 79, 37, 23, 21] 5.02510429763
-- 99 [96, 67, 20, 19, 13, 4] 6.27318537524
-- 99 [89, 73, 64, 60, 17, 6] 6.3922375882
k = 5, n = 5 (Tabel 2 from Lander and Parkin)
-- 72 [67, 47, 46, 43, 19] 0.211067094291
-- 94 [84, 79, 37, 23, 21] 0.604523412444
-- 107 [100, 80, 57, 43, 7] 1.00687568954
** 144 [133, 110, 84, 27] 3.26073688262
k = 5, n = 4
-- 144 [133, 110, 84, 27] 0.257228992944
"""
```
6. Marijn said

Somehow the superscript 5’s got left out of the 2 last terms, I found this in the html source: 133 = 144

7. programmingpraxis said

@Marijn: Fixed. Thanks.