/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection.euler;
import io.vavr.collection.CharSeq;
import io.vavr.collection.Seq;
import io.vavr.collection.List;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class Euler43Test {
/**
* <strong>Problem 43 Sub-string divisibility</strong>
* <p>
* The number, 1406357289, is a 0 to 9 pandigital number because it is made
* up of each of the digits 0 to 9 in some order, but it also has a rather
* interesting sub-string divisibility property.</p>
* <p>
* Let <i>d</i><sub>1</sub> be the 1<sup>st</sup> digit,
* <i>d</i><sub>2</sub> be the 2<sup>nd</sup> digit, and so on. In this way,
* we note the following:</p>
* <pre>
* <ul>
* <li><i>d</i><sub>2</sub><i>d</i><sub>3</sub><i>d</i><sub>4</sub>=406 is divisible by 2</li>
* <li><i>d</i><sub>3</sub><i>d</i><sub>4</sub><i>d</i><sub>5</sub>=063 is divisible by 3</li>
* <li><i>d</i><sub>4</sub><i>d</i><sub>5</sub><i>d</i><sub>6</sub>=635 is divisible by 5</li>
* <li><i>d</i><sub>5</sub><i>d</i><sub>6</sub><i>d</i><sub>7</sub>=357 is divisible by 7</li>
* <li><i>d</i><sub>6</sub><i>d</i><sub>7</sub><i>d</i><sub>8</sub>=572 is divisible by 11</li>
* <li><i>d</i><sub>7</sub><i>d</i><sub>8</sub><i>d</i><sub>9</sub>=728 is divisible by 13</li>
* <li><i>d</i><sub>8</sub><i>d</i><sub>9</sub><i>d</i><sub>10</sub>=289 is divisible by 17</li>
* </ul>
* </pre>
* <p>
* Find the sum of all 0 to 9 pandigital numbers with this property.
* <p>
* See also <a href="https://projecteuler.net/problem=43">projecteuler.net
* problem 43</a>.
*/
@Test
public void shouldSolveProblem43() {
final Seq<Long> result = tenDigitPandigitalsWithProperty();
Assertions.assertThat(result).contains(1406357289L);
assertThat(result.sum().longValue()).isEqualTo(16695334890L);
}
private static Seq<Long> tenDigitPandigitalsWithProperty() {
final CharSeq ALL_DIGITS = CharSeq.of("0123456789");
final List<Integer> DIVISORS = List.of(2, 3, 5, 7, 11, 13, 17);
return ALL_DIGITS
.combinations(2)
.flatMap(CharSeq::permutations)
.flatMap(firstTwoDigits -> DIVISORS
.foldLeft(List.of(firstTwoDigits), (accumulator, divisor) -> accumulator
.flatMap(digitsSoFar -> ALL_DIGITS
.removeAll(digitsSoFar)
.map(nextDigit -> digitsSoFar.append(nextDigit))
)
.filter(digitsToTest -> digitsToTest.takeRight(3).parseInt() % divisor == 0)
)
)
.map(tailDigitsWithProperty -> tailDigitsWithProperty
.prepend(ALL_DIGITS
.removeAll(tailDigitsWithProperty)
.head()
)
)
.map(CharSeq::parseLong);
}
}