Problem 9 — Special Pythagorean Triplet

solved Tue, 8 Oct 2019, 13:55 · level 0 · difficulty 1% projecteuler.net github

A Pythagorean triplet is a set of three natural numbers, $a \lt b \lt c$, for which, $$a^2 + b^2 = c^2.$$

For example, $3^2 + 4^2 = 9 + 16 = 25 = 5^2$.

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


Problem Analysis

A Pythagorean triple is a set of three positive integers a < b < c satisfying a2 + b2 = c2. Finding such integers is a Diophantine equation - an equation for which we admit only integer solutions. Here I add a second constraint, the linear equation a + b + c = S, and must find the unique Pythagorean triple satisfying both, then report the product abc.

The crucial observation is that the linear constraint lets me eliminate one variable. Once a and b are chosen, c is completely determined: c = S - a - b. This collapses what would naively be a three-dimensional search into a two-dimensional one. Two further observations bound the loops tightly. First, because a < b < c are all positive and sum to S, the smallest value a cannot exceed roughly S/4 - if a were any larger we could not fit two strictly greater values b and c that still sum to S. Second, b is bounded above by S/2 to keep c positive. Each candidate (a, b) pair is checked in constant time, so the overall complexity is O(S2). For S = 1000 that is on the order of 105 iterations - trivially fast in any language.

Solution Approach

Bounded two-variable search (index 0, Python and C)

Both the Python and C solutions implement the same algorithm. The outer loop iterates a from 1 up to S/4 inclusive - the tightest upper bound derivable from the ordering a < b < c. The inner loop iterates b from a (which enforces a ≤ b) up to S/2 (which keeps c positive). For each pair, c is computed directly as S - a - b rather than searched for. This is the variable-elimination step that removes an entire loop level. I then test whether a2 + b2 == c2 and, because the problem guarantees exactly one solution, return a*b*c immediately on the first match. The two nested loops give the O(S2) bound established above.

I deliberately compute c as an integer expression rather than taking a floating-point square root of a2 + b2. Integer arithmetic is exact, so the equality check is reliable; a floating-point approach would demand a tolerance comparison and risk rounding errors. The closed-form c = S - a - b sidesteps all of that.

The Python version wraps the nested loops in a generator expression and calls next() to retrieve the first result, converting the resulting StopIteration into a descriptive ValueError when no triple exists. The C version uses plain nested for loops with an early return, writing a diagnostic to stderr and returning -1 on failure. In C I cast to long long before the multiplication: although the answer 31875000 fits comfortably in a 32-bit int, the product of three loop variables could overflow for larger inputs, and promoting first is a cheap, defensive habit. Both versions handle the dev case (S = 12, the classic 3-4-5 triple, product 60) and the main case correctly.

workbench

Test cases

categoryinputanswer
dev sum_sides = 12 60
main sum_sides = 1000 31875000

Results

solutioncategoryanswerverdict avg seconds cavg seconds py
p0009_s0 dev 60 correct 0.000001 (105) 0.000002 (105)
p0009_s0 main 31875000 correct 0.000046 (105) 0.007332 (105)

Files

Tags & blogs

Blogs