mirror of
https://github.com/Crocmagnon/advent-of-code.git
synced 2024-11-05 22:33:59 +01:00
Solve day 12 part 2
This commit is contained in:
parent
37e8ea40f5
commit
66e11e3dac
2 changed files with 114 additions and 20 deletions
|
@ -9,32 +9,33 @@ def main(filename: str, expected_part_1: int = None, expected_part_2: int = None
|
||||||
instructions = f.read().strip().split("\n")
|
instructions = f.read().strip().split("\n")
|
||||||
|
|
||||||
counter_part_1 = solve_part_1(instructions)
|
counter_part_1 = solve_part_1(instructions)
|
||||||
counter_part_2 = 0
|
|
||||||
|
|
||||||
print(f"1. Found {counter_part_1}")
|
print(f"1. Found {counter_part_1}")
|
||||||
if expected_part_1:
|
if expected_part_1:
|
||||||
assert expected_part_1 == counter_part_1
|
assert expected_part_1 == counter_part_1
|
||||||
|
|
||||||
|
counter_part_2 = solve_part_2(instructions)
|
||||||
print(f"2. Found {counter_part_2}")
|
print(f"2. Found {counter_part_2}")
|
||||||
if expected_part_2:
|
if expected_part_2:
|
||||||
assert expected_part_2 == counter_part_2
|
assert expected_part_2 == counter_part_2
|
||||||
|
|
||||||
|
|
||||||
def solve_part_1(instructions: List[str]):
|
def solve_part_1(instructions: List[str]):
|
||||||
ship = Ship()
|
ship = ShipPart1()
|
||||||
|
ship.apply_instructions(instructions)
|
||||||
|
return ship.distance_from_origin
|
||||||
|
|
||||||
|
|
||||||
|
def solve_part_2(instructions: List[str]):
|
||||||
|
ship = ShipPart2()
|
||||||
ship.apply_instructions(instructions)
|
ship.apply_instructions(instructions)
|
||||||
return ship.distance_from_origin
|
return ship.distance_from_origin
|
||||||
|
|
||||||
|
|
||||||
class Ship:
|
class Ship:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.facing = Direction.EAST
|
self.vertical = 0
|
||||||
self.movements = {
|
self.horizontal = 0
|
||||||
Direction.NORTH: 0,
|
|
||||||
Direction.SOUTH: 0,
|
|
||||||
Direction.EAST: 0,
|
|
||||||
Direction.WEST: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
def apply_instructions(self, instructions):
|
def apply_instructions(self, instructions):
|
||||||
for instruction in instructions:
|
for instruction in instructions:
|
||||||
|
@ -42,25 +43,110 @@ class Ship:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def distance_from_origin(self):
|
def distance_from_origin(self):
|
||||||
return abs(
|
return abs(self.vertical) + abs(self.horizontal)
|
||||||
self.movements[Direction.NORTH] - self.movements[Direction.SOUTH]
|
|
||||||
) + abs(self.movements[Direction.EAST] - self.movements[Direction.WEST])
|
|
||||||
|
|
||||||
def apply_instruction(self, instruction):
|
@staticmethod
|
||||||
|
def parse_instruction(instruction):
|
||||||
letter = instruction[0]
|
letter = instruction[0]
|
||||||
value = int(instruction[1:])
|
value = int(instruction[1:])
|
||||||
|
return letter, value
|
||||||
|
|
||||||
|
def apply_instruction(self, instruction):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class ShipPart1(Ship):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.facing = Direction.EAST
|
||||||
|
|
||||||
|
def apply_instruction(self, instruction):
|
||||||
|
letter, value = self.parse_instruction(instruction)
|
||||||
if letter in Direction.values():
|
if letter in Direction.values():
|
||||||
direction = Direction(letter)
|
direction = Direction(letter)
|
||||||
self.move(direction, value)
|
self.move(direction, value)
|
||||||
elif letter == "F":
|
elif letter == "F":
|
||||||
self.move(self.facing, value)
|
self.move(self.facing, value)
|
||||||
elif letter in ["R", "L"]:
|
else:
|
||||||
|
self.turn(letter, value)
|
||||||
|
|
||||||
|
def move(self, direction: "Direction", value: int):
|
||||||
|
if direction == Direction.NORTH:
|
||||||
|
self.vertical += value
|
||||||
|
elif direction == Direction.SOUTH:
|
||||||
|
self.vertical -= value
|
||||||
|
elif direction == Direction.EAST:
|
||||||
|
self.horizontal += value
|
||||||
|
else:
|
||||||
|
self.horizontal -= value
|
||||||
|
|
||||||
|
def turn(self, letter, value):
|
||||||
if letter == "L":
|
if letter == "L":
|
||||||
value = -value
|
value = -value
|
||||||
self.facing = self.facing.turn(value)
|
self.facing = self.facing.turn(value)
|
||||||
|
|
||||||
def move(self, direction: "Direction", value: int):
|
|
||||||
self.movements[direction] += value
|
class ShipPart2(Ship):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.waypoint = (10, 1) # 10 units east, 1 unit north
|
||||||
|
|
||||||
|
def apply_instruction(self, instruction):
|
||||||
|
letter, value = self.parse_instruction(instruction)
|
||||||
|
if letter in Direction.values():
|
||||||
|
direction = Direction(letter)
|
||||||
|
self.move_waypoint(direction, value)
|
||||||
|
elif letter == "F":
|
||||||
|
self.move_to_waypoint(value)
|
||||||
|
else:
|
||||||
|
if letter == "L":
|
||||||
|
value = -value
|
||||||
|
self.turn_waypoint(value)
|
||||||
|
|
||||||
|
def move_waypoint(self, direction: "Direction", value: int):
|
||||||
|
if direction in [Direction.NORTH, Direction.SOUTH]:
|
||||||
|
if direction == Direction.SOUTH:
|
||||||
|
value = -value
|
||||||
|
self.waypoint = self.waypoint[0], self.waypoint[1] + value
|
||||||
|
else:
|
||||||
|
if direction == Direction.WEST:
|
||||||
|
value = -value
|
||||||
|
self.waypoint = self.waypoint[0] + value, self.waypoint[1]
|
||||||
|
|
||||||
|
def move_to_waypoint(self, number_of_times: int):
|
||||||
|
horizontal = self.waypoint[0] * number_of_times
|
||||||
|
self.horizontal += horizontal
|
||||||
|
vertical = self.waypoint[1] * number_of_times
|
||||||
|
self.vertical += vertical
|
||||||
|
|
||||||
|
def turn_waypoint(self, angle: int):
|
||||||
|
if angle == 0:
|
||||||
|
return
|
||||||
|
horizontal = self.waypoint[0]
|
||||||
|
vertical = self.waypoint[1]
|
||||||
|
top_right_quadrant = vertical >= 0 and horizontal >= 0
|
||||||
|
bottom_right_quadrant = vertical < 0 and horizontal >= 0
|
||||||
|
bottom_left_quadrant = vertical < 0 and horizontal < 0
|
||||||
|
if angle < 0:
|
||||||
|
if top_right_quadrant:
|
||||||
|
self.waypoint = -abs(vertical), abs(horizontal)
|
||||||
|
elif bottom_right_quadrant:
|
||||||
|
self.waypoint = abs(vertical), abs(horizontal)
|
||||||
|
elif bottom_left_quadrant:
|
||||||
|
self.waypoint = abs(vertical), -abs(horizontal)
|
||||||
|
else:
|
||||||
|
self.waypoint = -abs(vertical), -abs(horizontal)
|
||||||
|
return self.turn_waypoint(angle + 90)
|
||||||
|
else:
|
||||||
|
if top_right_quadrant:
|
||||||
|
self.waypoint = abs(vertical), -abs(horizontal)
|
||||||
|
elif bottom_right_quadrant:
|
||||||
|
self.waypoint = -abs(vertical), -abs(horizontal)
|
||||||
|
elif bottom_left_quadrant:
|
||||||
|
self.waypoint = -abs(vertical), abs(horizontal)
|
||||||
|
else:
|
||||||
|
self.waypoint = abs(vertical), abs(horizontal)
|
||||||
|
return self.turn_waypoint(angle - 90)
|
||||||
|
|
||||||
|
|
||||||
class Direction(enum.Enum):
|
class Direction(enum.Enum):
|
||||||
|
@ -100,5 +186,6 @@ class Direction(enum.Enum):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main("inputs/day12-test1", 25)
|
main("inputs/day12-test1", 25, 286)
|
||||||
main("inputs/day12")
|
main("inputs/day12-test2", None, 202)
|
||||||
|
main("inputs/day12", 1177, 46530)
|
||||||
|
|
7
2020/inputs/day12-test2
Normal file
7
2020/inputs/day12-test2
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
F10
|
||||||
|
N3
|
||||||
|
F7
|
||||||
|
R90
|
||||||
|
F11
|
||||||
|
L180
|
||||||
|
F10
|
Loading…
Reference in a new issue