/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection.euler; import io.vavr.Tuple; import io.vavr.collection.Stream; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; /** * <strong>Problem 28: Number spiral diagonals</strong> * <p> * Starting with the number 1 and moving to the right in a clockwise direction a * 5 by 5 spiral is formed as follows: * <pre> * 21 22 23 24 25 * 20 7 8 9 10 * 19 6 1 2 11 * 18 5 4 3 12 * 17 16 15 14 13 * </pre> * * It can be verified that the sum of the numbers on the diagonals is 101. * <p> * What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral * formed in the same way? * <p> * See also * <a href="https://projecteuler.net/problem=28">projecteuler.net problem 28 * </a>. */ public class Euler28Test { @Test public void shouldSolveProblem28() { assertThat(sumOfDiagonalInSpiralWithSide(5)).isEqualTo(101); assertThat(sumOfDiagonalInSpiralWithSide(1001)).isEqualTo(669_171_001); } private static long sumOfDiagonalInSpiralWithSide(long maxSideLength) { return diagonalNumbersInSpiralWithSide(maxSideLength).sum().longValue(); } private static Stream<Long> diagonalNumbersInSpiralWithSide(long maxSideLength) { return Stream.iterate(Tuple.of(1, center()), t -> Tuple.of(nextSideLength(t._1), nextRoundOfCorners(t._2.last(), nextSideLength(t._1)))) .takeWhile(t -> t._1 <= maxSideLength) .flatMap(t -> t._2); } private static Stream<Long> center() { return Stream.of(1L); } private static int nextSideLength(int currentSideLength) { return currentSideLength + 2; } private static Stream<Long> nextRoundOfCorners(long previousCorner, int currentSideLength) { return Stream.iterate(previousCorner, n -> n + currentSideLength - 1) .drop(1) .take(4); } }