Problem 45 — Triangular, Pentagonal, and Hexagonal

solved Wed, 4 Dec 2019, 11:56 · level 0 · difficulty 3% projecteuler.net github

Triangle, pentagonal, and hexagonal numbers are generated by the following formulae:

Triangle   $T_n=n(n+1)/2$   $1, 3, 6, 10, 15, \dots$
Pentagonal   $P_n=n(3n - 1)/2$   $1, 5, 12, 22, 35, \dots$
Hexagonal   $H_n=n(2n - 1)$   $1, 6, 15, 28, 45, \dots$

It can be verified that $T_{285} = P_{165} = H_{143} = 40755$.

Find the next triangle number that is also pentagonal and hexagonal.


Problem Analysis

This problem asks me to find a number that appears simultaneously in three figurate number sequences - triangular, pentagonal, and hexagonal. A figurate number is one that can be arranged into a regular geometric shape, and each of the three sequences here has a closed-form quadratic generator: T(n) = n(n+1)/2, P(n) = n(3n-1)/2, and H(n) = n(2n-1). I am told that 40755 is the smallest such common value (after the trivial 1) and must find the next one. A brute-force scan that generates all three sequences and intersects them would work, but there is a much sharper structural observation to be had first.

The decisive insight is an algebraic identity: every hexagonal number is also triangular. Substitute m = 2n-1 into the triangular formula and you get T(2n-1) = (2n-1)(2n)/2 = n(2n-1) = H(n). In other words, the hexagonal numbers are exactly the triangular numbers with odd index, so any number that is hexagonal is automatically triangular. That collapses a three-way intersection into a two-way one: I only need values that are simultaneously triangular (or equivalently hexagonal) and pentagonal. To test pentagonal membership efficiently I invert the formula. Solving P(k) = x with the quadratic formula gives k = (1 + sqrt(1 + 24x))/6, so x is pentagonal exactly when the discriminant 1 + 24x is a perfect square whose root is congruent to 5 mod 6 (making k a positive integer). Each test is constant-time arithmetic plus one square root, so scanning candidate triangular numbers and testing each is O(k) where k is the number of candidates examined before a hit - a tiny count in practice.

Solution Approach

Analytical Inverse-Formula Check (Python and C)

Both files implement the same algorithm. I start from a supplied index n - 285, which is the index of the known solution T(285) = 40755 - and increment n by one each iteration. For each n I compute the triangular number T(n) = n(n+1)/2 and apply two membership filters.

The first filter tests whether T(n) is pentagonal. From the inverse k = (1 + sqrt(1 + 24x))/6, k is a positive integer precisely when 1 + sqrt(1+24x) is divisible by 6, which means sqrt(1+24x) must be congruent to 5 mod 6. The code checks this directly: (1 + 24 * t) ** 0.5 % 6 == 5.0 in Python, and fmod(sqrt(1 + 24*t), 6.0) != 5.0 in C. This one comparison implicitly verifies that the discriminant is a perfect square - if it were not, the floating-point remainder would not land exactly on 5.0.

The second filter tests triangularity using k = (-1 + sqrt(1 + 8x))/2, which requires sqrt(1+8x) to be congruent to 3 mod 4: (1 + 8 * t) ** 0.5 % 4 == 3.0. Strictly this second filter is redundant - I am already iterating over triangular numbers, so T(n) is triangular by construction - but it keeps the formulation symmetric, self-contained, and trivially correct, and it costs almost nothing. When both filters pass, the value is returned. The answer is 1533776805.

The language-specific differences are purely mechanical. C uses fmod from <math.h> for the floating-point remainder and structures the filters with explicit continue statements; Python uses % on floats and nests two if blocks. Both rely on IEEE 754 double precision being exact for the integers involved (the answer is about 1.5 billion, well below 2^53), so the floating-point square roots are reliable.

workbench

Test cases

categoryinputanswer
main n = 285 1533776805

Results

solutioncategoryanswerverdict avg seconds cavg seconds py
p0045_s0 main 1533776805 correct 0.000509 (63) 0.010432 (63)

Files

Tags & blogs

Blogs