/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection.euler; import io.vavr.Function1; import io.vavr.collection.CharSeq; import io.vavr.collection.List; import io.vavr.collection.Stream; import org.assertj.core.api.Assertions; import org.junit.Test; import static io.vavr.collection.euler.Utils.file; import static io.vavr.collection.euler.Utils.readLines; import static org.assertj.core.api.Assertions.assertThat; public class Euler42Test { /** * <strong>Problem 42 Coded triangle numbers</strong> * <p> * The <i>n</i><sup>th</sup> term of the sequence of triangle numbers is * given by, <i>t</i><sub>n</sub> = ½<i>n</i>(<i>n</i>+1); so the first ten * triangle numbers are: * <pre> * 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... * </pre> * <p> * By converting each letter in a word to a number corresponding to its * alphabetical position and adding these values we form a word value. For * example, the word value for SKY is 19 + 11 + 25 = 55 = t<sub>10</sub>. If * the word value is a triangle number then we shall call the word a * triangle word. * <p> * Using p042_words.txt, a 16K text file containing nearly two-thousand * common English words, how many are triangle words? * <p> * See also <a href="https://projecteuler.net/problem=42">projecteuler.net * problem 42</a>. */ @Test public void shouldSolveProblem42() { assertThat(isTriangleWord("SKY")).isTrue(); assertThat(sumOfAlphabeticalPositions("SKY")).isEqualTo(55); assertThat(alphabeticalPosition('S')).isEqualTo(19); assertThat(alphabeticalPosition('K')).isEqualTo(11); assertThat(alphabeticalPosition('Y')).isEqualTo(25); assertThat(TRIANGLE_NUMBERS.take(10)).containsExactly(1, 3, 6, 10, 15, 21, 28, 36, 45, 55); List.rangeClosed(1, 60).forEach(n -> Assertions.assertThat(isTriangleNumberMemoized.apply(n)).isEqualTo(List.of(1, 3, 6, 10, 15, 21, 28, 36, 45, 55).contains(n))); assertThat(numberOfTriangleNumbersInFile()).isEqualTo(162); } private static int numberOfTriangleNumbersInFile() { return readLines(file("p042_words.txt")) .map(l -> l.replaceAll("\"", "")) .flatMap(l -> List.of(l.split(","))) .filter(Euler42Test::isTriangleWord) .length(); } private static boolean isTriangleWord(String word) { return isTriangleNumber(sumOfAlphabeticalPositions(word)); } private static boolean isTriangleNumber(int n) { return TRIANGLE_NUMBERS .takeWhile(t -> t <= n) .exists(t -> t == n); } private static final Function1<Integer, Boolean> isTriangleNumberMemoized = Function1.of(Euler42Test::isTriangleNumber).memoized(); private static final Stream<Integer> TRIANGLE_NUMBERS = Stream.from(1).map(n -> 0.5 * n * (n + 1)).map(Double::intValue); private static int sumOfAlphabeticalPositions(String word) { return CharSeq.of(word) .map(Euler42Test::alphabeticalPosition) .sum().intValue(); } private static int alphabeticalPosition(char c) { return c - 'A' + 1; } }