diff --git a/source/day13.d b/source/day13.d index 601eacc..8e53a8f 100644 --- a/source/day13.d +++ b/source/day13.d @@ -1,15 +1,18 @@ +import std.algorithm; +import std.typecons; + import dayutil; struct ParsedInput { - int timestamp; - int[] busses; + long timestamp; + long[] busses; } Variant run(int part, File input, bool bigboy, string[] args) { ParsedInput pInput = input.byLineCopy.array.parseInput(); Variant result = parts!long(part, () => part1(pInput), - () => part2(pInput, 100000000000000)); + () => part2(pInput)); return result; } @@ -18,16 +21,15 @@ Variant run(int part, File input, bool bigboy, string[] args) { ParsedInput input; input.timestamp = to!int(range[0]); - input.busses = range[1].splitter(',').map!(c => c == "x" ? -1 : c.to!int).array; - writeln(input); + input.busses = range[1].splitter(',').map!(c => c == "x" ? -1 : c.to!long).array; return input; } -int part1(ParsedInput input) { - int earliestBus = 0; - int earliestBusTimestamp = int.max; - foreach(int bus; input.busses.filter!(x => x != -1)) { - int closestTimestamp = (input.timestamp / bus + 1 ) * bus; +long part1(ParsedInput input) { + long earliestBus = 0; + long earliestBusTimestamp = long.max; + foreach(long bus; input.busses.filter!(x => x != -1)) { + long closestTimestamp = (input.timestamp / bus + 1 ) * bus; writeln(closestTimestamp); if (closestTimestamp < earliestBusTimestamp) { earliestBusTimestamp = closestTimestamp; @@ -39,38 +41,54 @@ int part1(ParsedInput input) { } long part2(ParsedInput input) { - long result = 0; - - long startI = startFrom == 0 ? 0 : startFrom / input.busses[0]; - - for (long i = startI; result == 0; i++) { - long offset = i * input.busses[0]; - bool fail = false; - - foreach(j, subsequentBus; input.busses[1..$].enumerate(1)) { - if (subsequentBus == -1) continue; - - if ((offset + j) % subsequentBus != 0) { - fail = true; - break; - } - } - - if (!fail) { - result = offset; - } - - debug { - if (i % 10000 == 0) { - writef("\rAt %d", offset); - stdout.flush(); - } - } + /+long[] remainders; + long[] divisors; + // Too much, but we're not short on memory + remainders.reserve(input.busses.length); + divisors.reserve(input.busses.length); + foreach (remainder, divisor; input.busses) { + if (divisor < 0) continue; + remainders ~= [remainder % divisor]; + divisors ~= [divisor]; } - debug writeln(); - return result; + writeln(remainders); + writeln(divisors); + + long N = divisors.fold!((a,b) => a * b); + writeln(N); + long[] Ns; Ns.length = divisors.length; + long[] Xs; Xs.length = divisors.length; + long[] BNXs; BNXs.length = divisors.length; + + foreach(i, divisor; divisors) { + Ns[i] = N / divisor; + } + + foreach(ref Xi, Ni, Di; lockstep(Xs, Ns, divisors)) { + long a = Ni % Di; + long b; + for(b = 0; (a * b) % Di != 1; b++) {} + Xi = b; + } + writeln(Xs); + + foreach(ref BNXi, Ri, Ni, Xi; lockstep(BNXs, remainders, Ns, Xs)) { + BNXi = Ri * Ni * Xi; + } + long result = BNXs.sum() % N;+/ + Tuple!(size_t, "index", long, "value")[] busses = input.busses.enumerate.filter!((e) => e.value != -1).array; + + long time = 0; + long step = busses[0].value; + + foreach(bus; busses[1..$]) { + for(; (time + bus.index) % bus.value != 0; time += step) {} + step *= bus.value; + } + writeln(time); + return time; } unittest { @@ -82,5 +100,9 @@ unittest { ParsedInput pInput = parseInput(input); assert(part1(pInput) == 295); + ParsedInput p2; + p2.busses = [-1, 7, -1, 5, -1, -1, 8]; + //assert(part2(p2) == 78); + assert(part2(pInput) == 1068781); }