diff --git a/in/13.txt b/in/13.txt new file mode 100644 index 0000000..abc266d --- /dev/null +++ b/in/13.txt @@ -0,0 +1,2 @@ +1011416 +41,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,911,x,x,x,x,x,x,x,x,x,x,x,x,13,17,x,x,x,x,x,x,x,x,23,x,x,x,x,x,29,x,827,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,19 diff --git a/source/app.d b/source/app.d index a3e8139..5188075 100644 --- a/source/app.d +++ b/source/app.d @@ -20,6 +20,7 @@ import day9; import day10; import day11; import day12; +import day13; import dayutil; immutable string progName = "aoc-2020"; @@ -41,6 +42,7 @@ Variant function(int, File, bool, string[])[] programs = [ &day10.run, &day11.run, &day12.run, + &day13.run, ]; void printUsage(string message = null) { diff --git a/source/day12.d b/source/day12.d index 72a39b4..85d3acc 100644 --- a/source/day12.d +++ b/source/day12.d @@ -18,7 +18,8 @@ struct Move { Variant run(int part, File input, bool bigboy, string[] args) { auto parsedInput = parseInput(input.byLine); return Variant(parts!int(part, - () => part1(parsedInput))); + () => part1(parsedInput), + () => part2(parsedInput))); } auto parseInput(Range)(Range range) if (isInputRange!Range && isSomeString!(ElementType!Range)) { @@ -57,6 +58,12 @@ auto parseInput(Range)(Range range) if (isInputRange!Range && isSomeString!(Elem }); } +int betterModulus(int number, int divisor) pure { + int tmp = number % divisor; + if (tmp < 0) tmp += divisor; + return tmp; +} + int part1(Range)(Range range) if (isInputRange!Range && is(ElementType!Range == Move)) { int x, y; Direction direction = Direction.EAST; @@ -81,14 +88,8 @@ int part1(Range)(Range range) if (isInputRange!Range && is(ElementType!Range == } } - int betterModulus(int number, int divisor) pure { - int tmp = number % divisor; - if (tmp < 0) tmp += divisor; - return tmp; - } - foreach(move; range) { - writefln("Facing %s (%d,%d)", direction, x, y); + //writefln("Facing %s (%d,%d)", direction, x, y); final switch(move.direction) { case Direction.NORTH: case Direction.SOUTH: @@ -111,6 +112,80 @@ int part1(Range)(Range range) if (isInputRange!Range && is(ElementType!Range == import std.math; return abs(x) + abs(y); } +int part2(Range)(Range range) if (isInputRange!Range && is(ElementType!Range == Move)) { + int waypointX = 10; + int waypointY = 1; + int x, y; + + foreach(move; range) { + //writefln("Ship (%d,%d), waypoint (%d,%d)", x, y, waypointX, waypointY); + final switch(move.direction) { + case Direction.NORTH: + waypointY += move.amount; + break; + case Direction.SOUTH: + waypointY -= move.amount; + break; + case Direction.WEST: + waypointX -= move.amount; + break; + case Direction.EAST: + waypointX += move.amount; + break; + case Direction.LEFT: + int direction = betterModulus(move.amount / 90, 4); + switch(direction) { + case 0: + break; + case 1: + int tmp = waypointY; + waypointY = waypointX; + waypointX = -tmp; + break; + case 2: + waypointY = -waypointY; + waypointX = -waypointX; + break; + case 3: + int tmp = waypointY; + waypointY = -waypointX; + waypointX = tmp; + break; + default: assert("Modulus went out of bounds"); + } + break; + case Direction.RIGHT: + int direction = betterModulus(move.amount / 90, 4); + switch(direction) { + case 0: + break; + case 1: + int tmp = waypointY; + waypointY = -waypointX; + waypointX = tmp; + break; + case 2: + waypointY = -waypointY; + waypointX = -waypointX; + break; + case 3: + int tmp = waypointY; + waypointY = waypointX; + waypointX = -tmp; + break; + default: assert("Modulus went out of bounds"); + } + break; + case Direction.FORWARD: + x += waypointX * move.amount; + y += waypointY * move.amount; + break; + } + } + + import std.math; + return abs(x) + abs(y); +} unittest { string input = q"EOS @@ -122,4 +197,5 @@ F11 EOS"; assert(parseInput(input.lineSplitter).part1() == 25); + assert(parseInput(input.lineSplitter).part2() == 286); } diff --git a/source/day13.d b/source/day13.d new file mode 100644 index 0000000..15d1c5e --- /dev/null +++ b/source/day13.d @@ -0,0 +1,51 @@ +import dayutil; + +struct ParsedInput { + int timestamp; + int[] busses; +} + +Variant run(int part, File input, bool bigboy, string[] args) { + ParsedInput pInput = input.byLineCopy.array.parseInput(); + Variant result = parts!int(part, + () => part1(pInput)); + return result; +} + + ParsedInput parseInput(Range)(Range range) if (isInputRange!Range && isSomeString!(ElementType!Range)) { + import std.conv; + ParsedInput input; + input.timestamp = to!int(range[0]); + + input.busses = range[1].splitter(',').filter!(c => c != "x").map!(to!int).array; + writeln(input); + return input; +} + +int part1(ParsedInput input) { + import std.math; + + int earliestBus = 0; + int earliestBusTimestamp = int.max; + foreach(int bus; input.busses) { + int closestTimestamp = (input.timestamp / bus + 1 ) * bus; + writeln(closestTimestamp); + if (closestTimestamp < earliestBusTimestamp) { + earliestBusTimestamp = closestTimestamp; + earliestBus = bus; + } + } + writefln("Bus %d at %d", earliestBus, earliestBusTimestamp); + return earliestBus * (earliestBusTimestamp - input.timestamp); +} + +unittest { + string[] input = [ + "939", + "7,13,x,x,59,x,31,19" + ]; + + ParsedInput pInput = parseInput(input); + + assert(part1(pInput) == 295); +}