## The 147 Puzzle

### February 5, 2013

Today’s exercise comes to us from the world of recreational mathematics:

Find all possible solutions to the equation 1/a + 1/b + 1/c + 1/d + 1/e = 1 where all of a, b, c, d and e are positive integers.

One solution is the trivial 1/5 + 1/5 + 1/5 + 1/5 + 1/5. Another solution, based on the perfect number 1 + 2 + 4 + 7 + 14 = 28, is 1/2 + 1/4 + 1/7 + 1/14 + 1/28. The minimum distinct solution is 1/3 + 1/4 + 1/5 + 1/6 + 1/20, where all the denominators are distinct and the sum of the denominators 3 + 4 + 5 + 6 + 20 = 38 is minimum over all solutions.

Your task is to write a program to enumerate all possible solutions to the equation. 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.

[…] today’s Programming Praxis exercise, our goal is to find all combinations of five numbers whose inverses […]

My Haskell solution (see http://bonsaicode.wordpress.com/2013/02/05/programming-praxis-the-147-puzzle/ for a version with comments):

A recursive Python version.

A cleaner and faster Python version.

[…] Pages: 1 2 […]

Here’s my Racket take:

http://blog.jverkamp.com/2013/02/06/the-147-puzzle/

Essentially, it ended up being a translation of Paul’s second solution into Racket. My original code was close, but I was missing a bit on the recursive bounds.

The procedure below passes the denominators of each solution to a

procedure which can be used to count or print them, or it can be

carefully crafted to generate the solutions on demand.

I got all confused about the limits and couldn’t work them out until I

took the hint from jpverkamp and copied the limits from Paul. Then my

procedure began to produce sensible results. I’m still not sure why my

lower limit differs by one from his, but it seems to work this way.

Perhaps it’s my obsession with the empty sum.

I guess recursion is the trickier way to solve this. Why not just iterate?

Also, if you multiply every term by abcde then you get an equation that doesn’t involve division or floats.

for(int a=1; a<10; a++)

{

for(int b=1; b<10; b++)

{

int ab = a*b;

for(int c=1; c<10; c++)

{

int abc = ab*c;

for(int d=1; d<10; d++)

{

int abcd = abc * d;

for(int e=1; e<10; e++)

{

if((b*c*d*e) + (a*c*d*e) + (ab*d*e) + (abc*e) + abcd == abcd*e)

printf("a=%d, b=%d, c=%d, d=%d, e=%d\n", a, b, c, d, e);

}

}

}

}

}

Re why not just iterate: The recursive solutions have the number of terms as a parameter. The same procedure, say f, solves f(1), f(2), f(3), f(4), f(5), and f(6). It solves also more, but after 6 the number of solutions becomes large.

Also, the solution to f(5) containing the largest denominator is (2, 3, 7, 43, 1806), so limiting the range of each denominator to single digits hides solutions. I don’t know if there is a way to know upper bounds to all denominators in advance.

None of the posted solutions use floats. They use exact rational arithmetic.

I think the largest denominator can be calculated (see the function lowest_series below. As you can see the largest denominator becomes very large. In that respect a recursive method works a lot nicer, as the lower and upper bounds can be dermined easily for the remaining terms.