Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

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

All Problems

Problem 196: Prime Triplets

View on Project Euler

Project Euler Problem 196 Solution

EulerSolve provides an optimized solution for Project Euler Problem 196, Prime Triplets, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary The positive integers are written in triangular rows: row \(r\) contains \(r\) consecutive values, from \(T_{r-1}+1\) to \(T_r\), where \(T_r=\frac{r(r+1)}{2}\). For a fixed row \(n\), the quantity \(S(n)\) is the sum of those primes in row \(n\) that belong to at least one prime triplet under the problem's neighborhood rule. The full task asks for \(S(5678027)+S(7208785)\). The key fact extracted from the implementations is that triplet membership is a purely local property: even for million-scale rows, the answer can be determined from a five-row strip centered on the target row. Mathematical Approach It is convenient to index the triangle by row and column. For \(0 \le c < r\), let $a(r,c)=\frac{r(r-1)}{2}+1+c,$ so \(a(r,c)\) is the value in row \(r\), column \(c\). Triangular Coordinates and the Neighborhood For each cell \((r,c)\), the implementations examine the clipped \(3\times3\) window $N(r,c)=\{(r+\Delta r,c+\Delta c): \Delta r,\Delta c\in\{-1,0,1\},\ 0\le c+\Delta c<r+\Delta r\}.$ This set contains the center cell itself, the two horizontal neighbors in the same row when they exist, and up to three cells in the row above and three in the row below. Interior cells therefore have eight neighbors; boundary cells have fewer because invalid coordinates are discarded. Let \(P(r,c)\) be 1 when \(a(r,c)\) is prime and 0 otherwise....

Detailed mathematical approach

Problem Summary

The positive integers are written in triangular rows: row \(r\) contains \(r\) consecutive values, from \(T_{r-1}+1\) to \(T_r\), where \(T_r=\frac{r(r+1)}{2}\). For a fixed row \(n\), the quantity \(S(n)\) is the sum of those primes in row \(n\) that belong to at least one prime triplet under the problem's neighborhood rule.

The full task asks for \(S(5678027)+S(7208785)\). The key fact extracted from the implementations is that triplet membership is a purely local property: even for million-scale rows, the answer can be determined from a five-row strip centered on the target row.

Mathematical Approach

It is convenient to index the triangle by row and column. For \(0 \le c < r\), let

$a(r,c)=\frac{r(r-1)}{2}+1+c,$

so \(a(r,c)\) is the value in row \(r\), column \(c\).

Triangular Coordinates and the Neighborhood

For each cell \((r,c)\), the implementations examine the clipped \(3\times3\) window

$N(r,c)=\{(r+\Delta r,c+\Delta c): \Delta r,\Delta c\in\{-1,0,1\},\ 0\le c+\Delta c<r+\Delta r\}.$

This set contains the center cell itself, the two horizontal neighbors in the same row when they exist, and up to three cells in the row above and three in the row below. Interior cells therefore have eight neighbors; boundary cells have fewer because invalid coordinates are discarded.

Let \(P(r,c)\) be 1 when \(a(r,c)\) is prime and 0 otherwise. Then the local prime count around \((r,c)\) is

$M(r,c)=\sum_{(u,v)\in N(r,c)} P(u,v).$

An Equivalent Criterion for Prime Triplets

The implementations rely on the following equivalent characterization. A prime at \((r,c)\) can act as the center of a prime triplet exactly when \(P(r,c)=1\) and \(M(r,c)\ge 3\). The reason is that the count \(M(r,c)\) includes the center itself, so a value of at least 3 means there are at least two additional primes in the same neighborhood.

This immediately gives the marking rule used in code: if a prime center has \(M(r,c)\ge 3\), then every prime in \(N(r,c)\) belongs to at least one valid triplet. The center is already adjacent to all of them, and there is always at least one more prime in the same neighborhood to complete a three-prime configuration. So the problem is not just to find centers; it is to mark every prime lying inside a qualifying neighborhood.

Why Only Five Rows Matter

Take any prime in row \(n\). If it belongs to a triplet, then either it is the center or it is adjacent to the center. In either case that center must lie in row \(n-1\), \(n\), or \(n+1\). Once the center is fixed, every cell in its neighborhood lies within one extra row, so all relevant values are contained in rows \(n-2\) through \(n+2\).

This is the central invariant of the solution. Instead of processing all values up to roughly \(\frac{n^2}{2}\), it is enough to inspect the exact interval covered by those five rows:

$\left[\frac{(n-2)(n-3)}{2}+1,\ \frac{(n+2)(n+3)}{2}\right].$

The total number of cells in that strip is

$ (n-2)+(n-1)+n+(n+1)+(n+2)=5n,$

so the relevant search space is linear in \(n\).

Segmented Sieving on the Exact Interval

Because the five-row strip is a contiguous block of integers, primality is determined with a segmented sieve on that interval. Only primes up to

$\sqrt{\frac{(n+2)(n+3)}{2}}$

are needed to cross out all composites. After sieving, the flat boolean array is projected back into five jagged rows, one for each triangular row from \(n-2\) to \(n+2\).

With that notation, the answer can be expressed as

$S(n)=\sum_{c=0}^{n-1} a(n,c)\,G(n,c),$

where \(G(n,c)=1\) exactly when \(a(n,c)\) is prime and lies inside \(N(r,d)\) for some prime center \((r,d)\) with \(r\in\{n-1,n,n+1\}\) and \(M(r,d)\ge 3\).

Worked Example: \(S(8)=60\) and \(S(9)=37\)

The small checkpoint rows show the method clearly. Row 8 is \(29,30,31,32,33,34,35,36\), while row 9 is \(37,38,39,40,41,42,43,44,45\). Consider the prime 23 in row 7. Its clipped neighborhood contains the numbers \(16,17,18,22,23,24,29,30,31\), and the primes among them are \(17,23,29,31\). Since that neighborhood already contains at least three primes, both 29 and 31 are certified as members of prime triplets, so \(S(8)=29+31=60\).

For row 9, the prime 37 lies at the left edge, so its neighborhood is smaller: \(29,30,37,38,46,47\). The prime subset is \(29,37,47\), which is still enough to form a triplet. By contrast, the primes 41 and 43 never appear inside any qualifying neighborhood of size at least three primes, so they do not contribute. Hence \(S(9)=37\). The large target rows are solved by exactly the same local logic.

How the Code Works

Sieving the Five-Row Strip

The C++, Python, and Java implementations first compute the start and end of the interval covering rows \(n-2\) through \(n+2\). They generate all base primes up to the square root of the interval endpoint, then mark composites inside the interval itself. The result is a primality table for every value that can possibly affect \(S(n)\).

Rebuilding the Triangle Shape

Next, the flat segmented-sieve array is mapped back into five row-shaped boolean arrays. One array records which cells are prime, and a second array records which prime cells have already been proved to belong to at least one triplet. This layout mirrors the triangular geometry, so neighborhood scans become simple bounded loops instead of repeated coordinate arithmetic on absolute values.

Scanning Candidate Centers and Marking Members

The implementations inspect only the middle three rows, because only those rows can contain a triplet center relevant to row \(n\). For each prime cell in those rows, the code counts primes in the clipped \(3\times3\) neighborhood. If the count is at least three, every prime in that neighborhood is marked. A final pass over row \(n\) sums exactly the marked primes.

The three languages differ only in low-level representation and in how the small supporting primes are generated. The mathematical workflow is the same in every version.

Complexity Analysis

The active interval has length exactly \(5n\), and every later step works only inside that strip. The neighborhood phase is linear as well: there are \(3n\) candidate-center positions in rows \(n-1\), \(n\), and \(n+1\), and each one inspects at most nine cells.

Using a standard segmented sieve, the running time is \(O(n \log \log n)\) in the usual sieve model, followed by an \(O(n)\) marking and summation pass. Extra space is \(O(n)\) for the interval primality array and the two five-row masks. The decisive optimization is locality: the algorithm never touches the whole triangle up to row \(n\), only the narrow strip that can influence the answer.

Footnotes and References

  1. Project Euler problem page: https://projecteuler.net/problem=196
  2. Prime number: Wikipedia - Prime number
  3. Triangular number: Wikipedia - Triangular number
  4. Sieve of Eratosthenes: Wikipedia - Sieve of Eratosthenes
  5. Segmented sieve overview: cp-algorithms - Sieve of Eratosthenes and segmented sieving

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

Previous: Problem 195 · All Project Euler solutions · Next: Problem 197

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! 🧮