# Project Euler 9 Solution: Special Pythagorean triplet

Problem 9

A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,

a2 + b2 = c2

For example, 32 + 42 = 9 + 16 = 25 = 52.

There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.

## Solution

A problem like this is perfect for Haskell, since we can transform the mathematical description par for par into a programm:

solution n = head [a * b * c |
c <- [1..n],
b <- [1..c],
a <- [1..b],
a^2 + b^2 == c^2,
a + b + c == n]

However, it takes quite some time to find the solution with this brute force attempt. One improvement is to use the fact that $$a+b+c=n$$ which let us construct the variable c as $$c=n - a - b$$ (we could construct c as $$c=\sqrt{a^2+b^2}$$, but this is computational much more expensive and of course we could construct a and b but this would require another check if the result becomes negative). This minimal change reduces the execution time tremendously, since we reduced the algorithm from $$O(n^3)$$ to $$O(n^2)$$:

solution n = head [a * b * c |
b <- [1..n],
a <- [1..b],
let c = n - a - b,
a^2 + b^2 == c^2]

In order to mind the given relation $$a<b<c$$, we would need to add a check of $$b<c$$, but as $$a^2+b^2=c^2 \Rightarrow b<c$$ for $$a>0$$, we can skip this test. But based on the fact that $$a<b<c$$ and $$a+b+c=n$$, we can conclude even more: The maximum possible $$a$$ and maximum possible $$b$$ is:

$a<\frac{n}{3} - 1$

$b<\frac{n}{2} - 1$

Since $$a$$ as this smallest number plus the sum of two other numbers shall not exceed $$n$$. The same takes effect for $$b$$ as this smallest number plus $$c$$ shall not exceed $$n$$. With this information, we can further reduce the search space:

solution n = head [a * b * c |
a <- [1..quot n 3],
b <- [a..quot n 2],
let c = n - a - b,
a^2 + b^2 == c^2]

We learned quite a lot already, but the search space is still too large, so back to the drawing board. We know $$a+b=n-c$$ and $$a^2+b^2=c^2$$, which lets us formulate

$\begin{array}{rrl}& a^2 + b^2 =& c^2\\\Leftrightarrow & a^2 + 2ab + b^2 =& c^2 + 2ab\\\Leftrightarrow & (a+b)^2 =& c^2 + 2ab\\\Leftrightarrow & 2ab =& (\underbrace{n-c}_{a+b})^2 - c^2\end{array}$

When subtracting the resulting equations from the starting equation, we get

$\begin{array}{rrl}& a^2 - 2ab + b^2 =& c^2 - (n-c)^2 + c^2\\\Leftrightarrow & (a-b)^2 =& c^2 - n^2 + 2nc - c^2 + c^2\\\Leftrightarrow & (a-b)^2 =& c^2 - n^2 + 2nc\end{array}$

Since $$(a-b)^2 = c^2 - n^2 + 2nc$$, we know the right part must be square. We achieved, that we completely removed a and b! As we constructed the triplet this way, we find a solution if the integer square root exists. Implementing all this knowledge leads to a solution which only depends on $$c$$ and calculates in linear time $$O(n)$$:

solution n = head [ a * b * c |
c <- [1 + quot n 3 .. quot n 2],
let sqa_b = c * c - n * n + 2 * n * c,
let a_b = floor(sqrt(fromIntegral sqa_b)),
let b = quot (n - c + a_b) 2,
let a = n - b - c,
a_b * a_b == sqa_b]

Or the same implemented in JavaScript:

function solution(n) {

for (var c = Math.floor(n / 3 + 1); c < n / 2; c++) {

var sqa_b = c * c - n * n + 2 * n * c
var a_b = Math.floor(Math.sqrt(sqa_b));

if (a_b * a_b == sqa_b) {
var b = (n - c + a_b) / 2;
var a = n - b - c;
return a * b * c;
}
}
return -1
}
solution(1000);


« Back to problem overview