2020-12-10 14:18:12 +01:00
|
|
|
import std;
|
|
|
|
|
2020-12-10 14:31:32 +01:00
|
|
|
alias Unit = void[0];
|
|
|
|
alias Set(T) = Unit[T];
|
|
|
|
|
|
|
|
auto toSet(R)(R r)
|
|
|
|
{
|
|
|
|
return r.map!(element => tuple(element, Unit.init)).assocArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto setOf(T)(T[] elements...)
|
|
|
|
{
|
|
|
|
return elements.toSet;
|
|
|
|
}
|
|
|
|
|
2020-12-10 14:18:12 +01:00
|
|
|
void main()
|
|
|
|
{
|
2020-12-10 14:31:32 +01:00
|
|
|
auto nodes = File("input", "r").byLine.map!(to!int).chain([0]).toSet;
|
2020-12-10 14:18:12 +01:00
|
|
|
nodes.calculateNumberOfPathsLeadingFromTo(0, nodes.byKey.maxElement).writeln;
|
|
|
|
}
|
|
|
|
|
2020-12-10 14:31:32 +01:00
|
|
|
ulong calculateNumberOfPathsLeadingFromTo(Set!int nodes, int start, int end)
|
2020-12-10 14:18:12 +01:00
|
|
|
{
|
|
|
|
if (end == start)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return iota(end - 3, end).filter!(potentialAncestor => potentialAncestor in nodes)
|
|
|
|
.map!(ancestor => nodes.memoize!calculateNumberOfPathsLeadingFromTo(start, ancestor))
|
|
|
|
.sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
2020-12-10 14:31:32 +01:00
|
|
|
Set!int input = setOf(0, 1);
|
2020-12-10 14:18:12 +01:00
|
|
|
assert(input.calculateNumberOfPathsLeadingFromTo(0, 1) == 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
2020-12-10 14:31:32 +01:00
|
|
|
auto input = [16, 10, 15, 5, 1, 11, 7, 19, 6, 12, 4].chain([0]).toSet;
|
2020-12-10 14:18:12 +01:00
|
|
|
assert(input.calculateNumberOfPathsLeadingFromTo(0, input.byKey.maxElement) == 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
|
|
|
auto input = [
|
|
|
|
28, 33, 18, 42, 31, 14, 46, 20, 48, 47, 24, 23, 49, 45, 19, 38, 39, 11,
|
|
|
|
1, 32, 25, 35, 8, 17, 7, 9, 4, 2, 34, 10, 3
|
2020-12-10 14:31:32 +01:00
|
|
|
].chain([0]).toSet;
|
2020-12-10 14:18:12 +01:00
|
|
|
assert(input.calculateNumberOfPathsLeadingFromTo(0, input.byKey.maxElement) == 19_208);
|
|
|
|
}
|