aoc2020/day12/part1/main.d

90 lines
2.4 KiB
D
Raw Normal View History

2020-12-19 13:48:12 +01:00
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);
}