/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection.euler; import io.vavr.Function1; import io.vavr.collection.Stream; import org.assertj.core.api.Assertions; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class Euler14Test { /** * <strong>Problem 14: Longest Collatz sequence</strong> * <p> * The following iterative sequence is defined for the set of positive integers: * <pre> * <code> * n → n/2 (n is even) * n → 3n + 1 (n is odd) * </code> * </pre> * Using the rule above and starting with 13, we generate the following sequence: * <pre> * <code> * 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1 * </code> * </pre> * It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. * Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1. * <p> * Which starting number, under one million, produces the longest chain? * <p> * NOTE: Once the chain starts the terms are allowed to go above one million. * <p> * See also <a href="https://projecteuler.net/problem=14">projecteuler.net problem 14</a>. */ @Test public void shouldSolveProblem14() { // equivalent to from(1L).take(1_000_000) Assertions.assertThat(Stream.from(500_000L) .take(500_000) .maxBy(collatzSequenceLength) .get()).isEqualTo(837799); } private final static Function1<Long, Long> collatzRecursive = n -> { if (n == 1) { return 1L; } else { if (n % 2 == 0) { return Euler14Test.collatzRecursive.apply(n / 2) + 1; } else { return Euler14Test.collatzRecursive.apply(3 * n + 1) + 1; } } }; private final static Function1<Long, Long> collatzSequenceLength = collatzRecursive.memoized(); }