Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

Complete solutions in C++, Python & Java — with step-by-step mathematical explanations

All Problems

Problem 139: Pythagorean Tiles

View on Project Euler

Project Euler Problem 139 Solution

EulerSolve provides an optimized solution for Project Euler Problem 139, Pythagorean Tiles, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary The problem asks for the number of Pythagorean triples \((a,b,c)\) with perimeter \(a+b+c<10^8\) that can form the classic “square hole” arrangement: four congruent right triangles are placed inside a \(c\times c\) square, leaving a central square of side \(|a-b|\). The arrangement becomes a genuine tiling only when that inner square side divides the outer side, so the arithmetic condition is $|a-b|\mid c.$ Rather than scan every non-primitive triple separately, the efficient strategy is to enumerate primitive triples first and then count all allowed multiples. Mathematical Approach The implementations are based on Euclid's parametrization of primitive Pythagorean triples, but the divisibility test hides a stronger structure. Once that structure is exposed, the code becomes easy to justify. The square hole and the divisibility invariant For a right triangle with legs \(a,b\) and hypotenuse \(c\), four copies fit inside a square of side \(c\). The central gap is itself a square, and a short geometric inspection shows that its side length is exactly $d=|a-b|.$ If the large square is to be tiled by smaller copies of that inner square pattern, the side length of the hole must divide the side length of the outer square. So the entire problem reduces to checking whether $d\mid c.$ This is the only arithmetic test used by the implementations....

Detailed mathematical approach

Problem Summary

The problem asks for the number of Pythagorean triples \((a,b,c)\) with perimeter \(a+b+c<10^8\) that can form the classic “square hole” arrangement: four congruent right triangles are placed inside a \(c\times c\) square, leaving a central square of side \(|a-b|\). The arrangement becomes a genuine tiling only when that inner square side divides the outer side, so the arithmetic condition is

$|a-b|\mid c.$

Rather than scan every non-primitive triple separately, the efficient strategy is to enumerate primitive triples first and then count all allowed multiples.

Mathematical Approach

The implementations are based on Euclid's parametrization of primitive Pythagorean triples, but the divisibility test hides a stronger structure. Once that structure is exposed, the code becomes easy to justify.

The square hole and the divisibility invariant

For a right triangle with legs \(a,b\) and hypotenuse \(c\), four copies fit inside a square of side \(c\). The central gap is itself a square, and a short geometric inspection shows that its side length is exactly

$d=|a-b|.$

If the large square is to be tiled by smaller copies of that inner square pattern, the side length of the hole must divide the side length of the outer square. So the entire problem reduces to checking whether

$d\mid c.$

This is the only arithmetic test used by the implementations.

Primitive triples through Euclid's formula

Every primitive Pythagorean triple can be written uniquely as

$a=m^2-n^2,\qquad b=2mn,\qquad c=m^2+n^2,$

with integers \(m>n\ge 1\), \(\gcd(m,n)=1\), and \(m-n\) odd. Its perimeter is

$P=a+b+c=2m(m+n).$

This gives the search space used in the code: loop over admissible pairs \((m,n)\), build the primitive triple, and test the tiling condition.

Why a primitive tiling triple must satisfy \(|a-b|=1\)

Let \(d=|a-b|\) for a primitive triple. If the tiling condition holds, then \(d\mid c\). Since \(d\mid(a-b)\) as well, we also have

$d\mid c^2-(a-b)^2.$

Using \(c^2=a^2+b^2\), this becomes

$c^2-(a-b)^2=a^2+b^2-(a^2-2ab+b^2)=2ab,$

so \(d\mid 2ab\).

Now use the primitive-triple facts. We have \(\gcd(a,b)=1\), one leg is even, the other is odd, and therefore \(d=|a-b|\) is odd. Also

$\gcd(d,a)=\gcd(a-b,a)=\gcd(a,b)=1,\qquad \gcd(d,b)=1.$

Thus \(d\) is coprime to \(2\), to \(a\), and to \(b\), yet it divides \(2ab\). The only possibility is

$d=1.$

Conversely, \(d=1\) obviously implies \(d\mid c\). So for primitive triples the condition is equivalent to saying that the two legs are consecutive integers.

The Pell-type description of the primitive solutions

Substituting Euclid's formula into \(|a-b|=1\) gives

$|m^2-n^2-2mn|=1,$

or, after setting \(x=m-n\) and \(y=n\),

$|x^2-2y^2|=1.$

This is the Pell equation \(x^2-2y^2=\pm1\). Therefore the primitive tiling triples form a Pell family, equivalently an “almost isosceles” family with consecutive legs. One convenient recurrence for the Euclid parameters is

$m_{k+1}=2m_k+n_k,\qquad n_{k+1}=m_k,$

starting from \((m_1,n_1)=(2,1)\). It produces

$ (3,4,5),\ (20,21,29),\ (119,120,169),\ (696,697,985),\dots $

The implementations do not generate this recurrence explicitly, but the divisibility test they apply is exactly selecting this same family from the full Euclid search.

Counting all non-primitive triples

If \((a,b,c)\) is a qualifying primitive triple, then every multiple

$\bigl(ka,kb,kc\bigr)$

also qualifies, because

$|ka-kb|=k|a-b|$

and divisibility is preserved. If the primitive perimeter is \(P\), then the allowed values of \(k\) satisfy

$kP<10^8,$

so the number of counted multiples is

$\left\lfloor\frac{10^8-1}{P}\right\rfloor.$

This explains the accumulation formula used in all three implementations.

Worked example: the checkpoint at 100

For perimeter \(P<100\), the primitive tiling triples are exactly

$ (3,4,5)\ (P=12),\qquad (20,21,29)\ (P=70). $

All qualifying triples below 100 come from their multiples:

$\left\lfloor\frac{99}{12}\right\rfloor=8,\qquad \left\lfloor\frac{99}{70}\right\rfloor=1.$

Therefore the total count is

$8+1=9,$

which is exactly the checkpoint used by the C++ implementation.

How the Code Works

Enumerating primitive generators

The C++, Python, and Java implementations loop over Euclid parameters \(m>n\). The outer loop stops as soon as the smallest perimeter for that \(m\), namely \(2m(m+1)\), reaches the limit. Inside, the code keeps only coprime pairs of opposite parity, which are precisely the primitive generators.

Applying the tiling test

For each admissible pair \((m,n)\), the implementation constructs \(a\), \(b\), \(c\), and the leg difference \(d=|a-b|\). It then checks the single condition \(c\bmod d=0\). That condition is mathematically equivalent to selecting the consecutive-leg Pell family, but the code keeps the test in this direct arithmetic form.

Accumulating all scaled copies

Once a primitive triple passes the divisibility test, its perimeter \(P\) is known. Every scaled copy with \(kP<10^8\) is counted, so the contribution added to the answer is \(\left\lfloor(10^8-1)/P\right\rfloor\). The three implementations differ only in language syntax; their control flow and counting logic are the same.

Complexity Analysis

Let \(L=10^8\). Since the outer loop stops when \(2m(m+1)\ge L\), we have \(m=O(\sqrt{L})\). For each \(m\), the inner loop scans \(n=1,2,\dots,m-1\), so the total number of candidate Euclid pairs is \(O(L)\).

Each candidate requires a gcd computation and a constant amount of integer arithmetic, giving \(O(L\log L)\) time in a strict arithmetic model, or effectively linear time in the number of tested pairs on fixed-size machine integers. Memory usage is \(O(1)\), because the implementation stores only a handful of integers and the running total.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=139
  2. Pythagorean triples: Wikipedia - Pythagorean triple
  3. Euclid's parametrization: Wikipedia - Generating a triple
  4. Pell equation: Wikipedia - Pell's equation
  5. Continued fractions and \(\sqrt{2}\): Wikipedia - Continued fraction

Mathematical approach · C++ solution · Python solution · Java solution

Previous: Problem 138 · All Project Euler solutions · Next: Problem 140

Need help with a problem? Ask me! 💡
e
✦ Euler GLM 5.2
Hi! I'm Euler. Ask me anything about Project Euler problems, math concepts, or solution approaches! 🧮