aoc2020/day12/part2/main.d

72 lines
2.2 KiB
D
Raw Normal View History

2020-12-19 13:48:12 +01:00
import std;
void main()
{
slurp!(char, long)("input", "%c%d").getManhattanDistanceForInstructions.writeln;
}
alias Instruction = Tuple!(char, long);
alias RelativeWaypoint = Tuple!(long, long);
auto rotateLeft(RelativeWaypoint relativeWaypoint, long n)
{
n = (n + 4) % 4;
if (n == 0)
return relativeWaypoint;
return tuple(-relativeWaypoint[1], relativeWaypoint[0]).rotateLeft(n - 1);
}
struct ShipState
{
immutable long posX = 0;
immutable long posY = 0;
RelativeWaypoint relativeWaypoint = tuple(10, 1);
ShipState withInstructionApplied(Instruction instruction)
{
return [
'E': (long value) => ShipState(posX, posY,
tuple(relativeWaypoint[0] + value, relativeWaypoint[1])),
'N': (long value) => ShipState(posX, posY,
tuple(relativeWaypoint[0], relativeWaypoint[1] + value)),
'W': (long value) => ShipState(posX, posY,
tuple(relativeWaypoint[0] - value, relativeWaypoint[1])),
'S': (long value) => ShipState(posX, posY,
tuple(relativeWaypoint[0], relativeWaypoint[1] - value)),
'L': (long value) => ShipState(posX, posY,
relativeWaypoint.rotateLeft(value / 90)),
'R': (long value) => ShipState(posX, posY,
relativeWaypoint.rotateLeft((360 - value) / 90)),
'F': (long value) => ShipState(posX + relativeWaypoint[0] * value,
posY + relativeWaypoint[1] * value, relativeWaypoint)
][instruction[0]](instruction[1]);
}
ShipState withInstructionsApplied(Instruction[] instructions)
{
if (instructions.empty)
{
return this;
}
return withInstructionApplied(instructions[0]).withInstructionsApplied(instructions[1 .. $]);
}
}
auto getManhattanDistanceForInstructions(Instruction[] instructions)
{
auto finalState = ShipState().withInstructionsApplied(instructions);
return abs(finalState.posX) + abs(finalState.posY);
}
unittest
{
auto input = [
tuple('F', 10L), tuple('N', 3L), tuple('F', 7L), tuple('R', 90L),
tuple('F', 11L)
];
assert(input.getManhattanDistanceForInstructions == 286);
}