Advent Of Code Day 12: Manhattan Rains
For Day 12, the problem revolves around navigating a ship using a set of navigational instructions. The instructions look like this:
F10
N3
F7
R90
F11
F2
F2
F2
R180
F10
The instructions move the ship in a cardinal direction N, S, E, W, Rotate the ship, or move Forward, using the current rotation. This problem is solved easily with a simple navigation routine:
def navigate(steps, visualize):
states = []
ship = Position(0, 0)
heading = 0
if visualize:
states.append(ShipState(ship, heading, None))
for action, value in steps:
if action == "N":
ship.y += value
elif action == "S":
ship.y -= value
elif action == "E":
ship.x += value
elif action == "W":
ship.x -= value
elif action == "L":
heading += value
heading = heading % 360
elif action == "R":
heading -= value
heading = heading % 360
elif action == "F":
if heading == 0:
ship.x += value
elif heading == 90:
ship.y += value
elif heading == 180:
ship.x -= value
elif heading == 270:
ship.y -= value
if visualize:
states.append(ShipState(ship, heading, None))
return ship, states
The “F” action block would be perfect for a switch
statement, if
only Python had them.
The answer to the puzzle is the Manhattan distance from the starting point, after all steps have been executed.
A small test execution:
Part 2 was essentially the same, but instead of rotating the ship, the target waypoint is moved, and the F directive move the ship to the waypoint. This can be done with an almost identical routine:
waypoint = Position(10, 1)
ship = Position(0, 0)
for action, value in steps:
if action == "N":
waypoint.y += value
elif action == "S":
waypoint.y -= value
elif action == "E":
waypoint.x += value
elif action == "W":
waypoint.x -= value
elif action == "L":
for _ in range(value // 90):
waypoint.x, waypoint.y = -waypoint.y, waypoint.x
elif action == "R":
for _ in range(value // 90):
waypoint.x, waypoint.y = waypoint.y, -waypoint.x
elif action == "F":
ship.x += waypoint.x * value
ship.y += waypoint.y * value