/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection.euler; import io.vavr.collection.Stream; import io.vavr.collection.List; import org.assertj.core.api.Assertions; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class Euler45Test { /** * <strong>Problem 45 Triangular, pentagonal, and hexagonal</strong> * * <p>Triangle, pentagonal, and hexagonal numbers are generated by the following formulae:</p> * <p>Triangle Tn=n(n+1)/2 1, 3, 6, 10, 15, ...</p> * <p>Pentagonal Pn=n(3n−1)/2 1, 5, 12, 22, 35, ...</p> * <p>Hexagonal Hn=n(2n−1) 1, 6, 15, 28, 45, ...</p> * * <p> * It can be verified that T285 = P165 = H143 = 40755. * Find the next triangle number that is also pentagonal and hexagonal. * </p> * * See also <a href="https://projecteuler.net/problem=45">projecteuler.net * problem 45</a>. */ @Test public void shouldSolveProblem45() { assertThat(List.of(5, 12, 22, 35)).allMatch(Euler45Test::isPentagonal); assertThat(List.of(3, 11, 21, 36)).allMatch(i -> !isPentagonal(i)); Assertions.assertThat(HEXAGONAL.take(5)).containsExactly(6L, 15L, 28L, 45L, 66L); assertThat(HEXAGONAL .filter(Euler45Test::isPentagonal) .head()) .isEqualTo(40755); assertThat(HEXAGONAL .filter(Euler45Test::isPentagonal) .tail() .head()) .isEqualTo(1533776805L); } private static final Stream<Long> HEXAGONAL = Stream.from(2L).map(i -> i*(2*i -1)); private static boolean isPentagonal(long i) { // If a number k is pentagonal then n(3n−1)/2 = k; for some integer n // by the quadratic formula (1+sqrt(1+4*3*2k))/6 = n long discriminant = 1+24*i; return isPerfectSquare(discriminant) && (1 + flooredRoot(discriminant)) % 6 == 0; } private static boolean isPerfectSquare(long i) { long sqrtFloor = flooredRoot(i); return sqrtFloor*sqrtFloor == i; } private static long flooredRoot(long i) { return (long)Math.sqrt(i+0.5); } }