diff --git a/day12/day12.cpp b/day12/day12.cpp index 04e3842..40573d4 100644 --- a/day12/day12.cpp +++ b/day12/day12.cpp @@ -9,15 +9,23 @@ constexpr int NUM_DIRECTIONS = 4; enum CardinalDirection { NORTH = 0, EAST = 1, SOUTH = 2, WEST = 3 }; -class Ship { +class MovablePoint { public: - Ship(CardinalDirection direction, std::pair position) : direction(direction), position(position) { + MovablePoint(CardinalDirection direction, std::pair position) : direction(direction), position(position) { } const std::pair &getPosition() const { return this->position; } + void setPosition(const std::pair &position) { + this->position = position; + } + + void setPosition(std::pair &&position) { + this->position = position; + } + CardinalDirection getDirection() const { return direction; } @@ -31,7 +39,7 @@ class Ship { } void move(int value, CardinalDirection direction) { - int delta = (direction == SOUTH || direction == EAST) ? -value : value; + int delta = (direction == SOUTH || direction == WEST) ? -value : value; if (direction == NORTH || direction == SOUTH) { this->position.second += delta; } else { @@ -48,6 +56,29 @@ class Ship { this->addToDirection(deg / 90); } + void rotatePosition(int degrees) { + int x = this->position.first; + int y = this->position.second; + // This is an awful way of writing a rotation, but it basically just hacking in the three parts of the rotation + // matrix I need + auto stepAmount = degrees / abs(degrees / 90); + if (abs(stepAmount) != 90) { + throw std::invalid_argument("Invalid rotation amount"); + } + for (int i = 0; i < abs(degrees / 90); i++) { + int tmpX = x; + x = -y; + y = tmpX; + if (stepAmount < 0) { + x *= -1; + y *= -1; + } + } + + this->position.first = x; + this->position.second = y; + } + private: void addToDirection(int delta) { this->direction = static_cast((this->direction + delta) % NUM_DIRECTIONS); @@ -86,7 +117,7 @@ std::vector> parseInput(const std::vector &inp return parsedInput; } -void makeMove(Ship &ship, const std::pair &move) { +void moveShip(MovablePoint &ship, const std::pair &move) { char directive = move.first; int magnitude = move.second; switch (directive) { @@ -116,10 +147,53 @@ void makeMove(Ship &ship, const std::pair &move) { } } +void moveShipOrWaypoint(MovablePoint &ship, MovablePoint &waypoint, const std::pair &move) { + char directive = move.first; + int magnitude = move.second; + switch (directive) { + case 'L': + waypoint.rotatePosition(magnitude); + break; + case 'R': + waypoint.rotatePosition(-magnitude); + break; + case 'N': + waypoint.move(magnitude, NORTH); + break; + case 'S': + waypoint.move(magnitude, SOUTH); + break; + case 'E': + waypoint.move(magnitude, EAST); + break; + case 'W': + waypoint.move(magnitude, WEST); + break; + case 'F': { + auto shipPosition = ship.getPosition(); + shipPosition.first += waypoint.getPosition().first * magnitude; + shipPosition.second += waypoint.getPosition().second * magnitude; + ship.setPosition(std::move(shipPosition)); + } break; + default: + throw std::invalid_argument("Invalid move direction"); + } +} + int part1(const std::vector> &input) { - Ship ship(EAST, std::pair(0, 0)); + MovablePoint ship(EAST, std::pair(0, 0)); for (auto &move : input) { - makeMove(ship, move); + moveShip(ship, move); + } + + return abs(ship.getPosition().first) + abs(ship.getPosition().second); +} + +int part2(const std::vector> &input) { + MovablePoint ship(EAST, std::pair(0, 0)); + MovablePoint waypoint(EAST, std::pair(10, 1)); + for (auto &move : input) { + moveShipOrWaypoint(ship, waypoint, move); } return abs(ship.getPosition().first) + abs(ship.getPosition().second); @@ -135,4 +209,5 @@ int main(int argc, char *argv[]) { auto parsedInput = parseInput(input); std::cout << part1(parsedInput) << std::endl; + std::cout << part2(parsedInput) << std::endl; }