import aoclib DAY = 12 TEST_SOLUTION_PART1 = 25 TEST_SOLUTION_PART2 = 286 FACING = ['N', 'E', 'S', 'W'] class Ship: def __init__(self, waypoint_mode=False, posShipX=0, posShipY=0, posWaypointX=0, posWaypointY=0, facing=0): self.pos = [ { 'x': posShipX, 'y': posShipY }, { 'x': posWaypointX, 'y': posWaypointY } ] self.waypoint_mode = waypoint_mode self.facing = facing def move(self, direction, distance): if direction == 'F': if self.waypoint_mode: self.pos[0]['x'] += self.pos[1]['x'] * distance self.pos[0]['y'] += self.pos[1]['y'] * distance return else: direction = FACING[self.facing] if direction == 'N': self.pos[self.waypoint_mode]['y'] -= distance elif direction == 'S': self.pos[self.waypoint_mode]['y'] += distance elif direction == 'E': self.pos[self.waypoint_mode]['x'] += distance elif direction == 'W': self.pos[self.waypoint_mode]['x'] -= distance elif direction == 'R': if not self.waypoint_mode: self.facing = (self.facing + int(distance / 90)) % 4 else: for i in range(int(distance / 90)): self.pos[1]['x'], self.pos[1]['y'] = -self.pos[1]['y'], self.pos[1]['x'] elif direction == 'L': if not self.waypoint_mode: self.facing = (self.facing - int(distance / 90)) % 4 else: for i in range(int(distance / 90)): self.pos[1]['x'], self.pos[1]['x'] = self.pos[1]['y'], -self.pos[1]['x'] def getManhattanDistance(self, startX=0, startY=0): return abs(self.pos[0]['x'] + startX) + abs(self.pos[0]['y'] + startY) def part1(test_mode=False): my_input = aoclib.getInputAsArray(day=DAY, test=test_mode) ship = Ship(facing=1) for instruction in my_input: ship.move(instruction[0], int(instruction[1:])) return ship.getManhattanDistance() def part2(test_mode=False): my_input = aoclib.getInputAsArray(day=DAY, test=test_mode) ship = Ship(waypoint_mode=True, posWaypointX=10, posWaypointY=-1, facing=1) for instruction in my_input: ship.move(instruction[0], int(instruction[1:])) return ship.getManhattanDistance()