71 lines
2.2 KiB
D
71 lines
2.2 KiB
D
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);
|
|
}
|