/*  __    __  __  __    __  ___
 * \  \  /  /    \  \  /  /  __/
 *  \  \/  /  /\  \  \/  /  /
 *   \____/__/  \__\____/__/
 *
 * Copyright 2014-2020 Vavr, http://vavr.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.vavr.collection.euler;

import io.vavr.collection.Stream;
import org.junit.Test;

import static io.vavr.collection.euler.Utils.factors;
import static org.assertj.core.api.Assertions.assertThat;

public class Euler12Test {

    /**
     * <strong>Problem 12: Highly divisible triangular number</strong>
     * <p>
     * The sequence of triangle numbers is generated by adding the natural
     * numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 =
     * 28. The first ten terms would be:
     * <p>
     * 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
     * <p>
     * Let us list the factors of the first seven triangle numbers:
     * <pre>
     * 1: 1
     * 3: 1,3
     * 6: 1,2,3,6
     * 10: 1,2,5,10
     * 15: 1,3,5,15
     * 21: 1,3,7,21
     * 28: 1,2,4,7,14,28
     * </pre>
     * <p>
     * We can see that 28 is the first triangle number to have over five
     * divisors.
     * <p>
     * What is the value of the first triangle number to have over five hundred
     * divisors?
     */
    @Test
    public void shouldSolveProblem12() {
        assertThat(valueOfFirstTriangleNumberWithMoreDivisorsThan(5)).isEqualTo(28);
        assertThat(valueOfFirstTriangleNumberWithMoreDivisorsThan(500)).isEqualTo(76_576_500);
    }

    private static long valueOfFirstTriangleNumberWithMoreDivisorsThan(long divisorCount) {
        return triangleNumbers()
                .find(t -> divisorCount(t) > divisorCount)
                .get();
    }

    private static Stream<Long> triangleNumbers() {
        return Stream.from(1L).scanLeft(0L, (a, l) -> a + l);
    }

    private static long divisorCount(long number) {
        return factors(number).length();
    }
}
