/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection.euler; import io.vavr.Tuple; import io.vavr.collection.Map; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.collection.List; import org.junit.Test; import static java.lang.Math.floor; import static java.lang.Math.hypot; import static io.vavr.control.Option.some; import static org.assertj.core.api.Assertions.assertThat; public class Euler39Test { /** * <strong>Problem 39 Integer right triangles</strong> * <p> * If <i>p</i> is the perimeter of a right angle triangle with integral * length sides, {<i>a,b,c</i>}, there are exactly three solutions for * <i>p</i> = 120. * <p> * {20,48,52}, {24,45,51}, {30,40,50} * <p> * For which value of <i>p</i> ≤ 1000, is the number of solutions maximised? * <p> * See also <a href="https://projecteuler.net/problem=39">projecteuler.net * problem 39</a>. */ @Test public void shouldSolveProblem39() { assertThat(SOLUTIONS_FOR_PERIMETERS_UP_TO_1000.get(120)).isEqualTo(some(List.of(Tuple.of(20, 48, 52), Tuple.of(24, 45, 51), Tuple.of(30, 40, 50)))); assertThat(perimeterUpTo1000WithMaximisedNumberOfSolutions()).isEqualTo(840); } private static int perimeterUpTo1000WithMaximisedNumberOfSolutions() { return SOLUTIONS_FOR_PERIMETERS_UP_TO_1000 .map((perimeter, listOfSolutions) -> Tuple.of(perimeter, listOfSolutions.length())) .maxBy(Tuple2::_2) .get()._1; } private static final Map<Integer, List<Tuple3<Integer, Integer, Integer>>> SOLUTIONS_FOR_PERIMETERS_UP_TO_1000 = List.rangeClosed(1, 500) .flatMap(a -> List.rangeClosed(a, 500) .map(b -> Tuple.of(a, b, hypot(a, b)))) .filter(t -> floor(t._3) == t._3) .map(t -> t.map3(Double::intValue)) .groupBy(t -> t.apply((a, b, c) -> a + b + c)) .filterKeys(d -> d <= 1_000); }