90 lines
2.4 KiB
D
90 lines
2.4 KiB
D
|
import std;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
slurp!(char, ulong)("input", "%c%d").getManhattanDistanceForInstructions.writeln;
|
||
|
}
|
||
|
|
||
|
enum Direction
|
||
|
{
|
||
|
east = 0,
|
||
|
north = 1,
|
||
|
west = 2,
|
||
|
south = 3
|
||
|
}
|
||
|
|
||
|
alias Instruction = Tuple!(char, ulong);
|
||
|
|
||
|
struct ShipState
|
||
|
{
|
||
|
immutable long posX = 0;
|
||
|
immutable long posY = 0;
|
||
|
immutable Direction direction = Direction.east;
|
||
|
|
||
|
private auto calculateXMovement(Direction direction, ulong value)
|
||
|
{
|
||
|
switch (direction) with (Direction)
|
||
|
{
|
||
|
case east:
|
||
|
return value;
|
||
|
case west:
|
||
|
return -value;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private auto calculateYMovement(Direction direction, ulong value)
|
||
|
{
|
||
|
switch (direction) with (Direction)
|
||
|
{
|
||
|
case north:
|
||
|
return value;
|
||
|
case south:
|
||
|
return -value;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ShipState withInstructionApplied(Instruction instruction)
|
||
|
{
|
||
|
return [
|
||
|
'E': (ulong value) => ShipState(posX + value, posY, direction),
|
||
|
'N': (ulong value) => ShipState(posX, posY + value, direction),
|
||
|
'W': (ulong value) => ShipState(posX - value, posY, direction),
|
||
|
'S': (ulong value) => ShipState(posX, posY - value, direction),
|
||
|
'L': (ulong value) => ShipState(posX, posY,
|
||
|
((direction + value / 90) % 4).to!Direction),
|
||
|
'R': (ulong value) => ShipState(posX, posY,
|
||
|
((direction - value / 90 + 4) % 4).to!Direction),
|
||
|
'F': (ulong value) => ShipState(posX + calculateXMovement(direction,
|
||
|
value), posY + calculateYMovement(direction, value), direction)
|
||
|
][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', 10UL), tuple('N', 3UL), tuple('F', 7UL), tuple('R', 90UL),
|
||
|
tuple('F', 11UL)
|
||
|
];
|
||
|
assert(input.getManhattanDistanceForInstructions == 25);
|
||
|
}
|