Advertisement
Guest User

Advent of Code Day 12

a guest
Dec 12th, 2020
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.55 KB | None | 0 0
  1. """Day 12 of Advent of Code 2020 Solution"""
  2. from collections import deque
  3.  
  4.  
  5. def direction_io(file_location):
  6.     directions = []
  7.     with open(file_location, "r") as f:
  8.         for line in f.readlines():
  9.             directions.append((line[0], int(line[1:])))
  10.         return directions
  11.  
  12.  
  13. class ShipNavigation:
  14.     COMPASS = {
  15.         "N": complex(0, 1),
  16.         "S": complex(0, -1),
  17.         "E": complex(1, 0),
  18.         "W": complex(-1, 0),
  19.     }
  20.     ROTATION_DIRECTION = {"L": 1, "R": -1}
  21.  
  22.     def __init__(self, position=complex(0, 0), rotations=deque(["E", "S", "W", "N"])):
  23.         self.position: complex = position
  24.         self.rotations: deque[str] = rotations
  25.  
  26.     def __add__(self, direction_distance: tuple[str, int]):
  27.         direction, distance = direction_distance
  28.         if direction in "RL":
  29.             self.rotate(direction, distance)
  30.         else:
  31.             if direction == "F":
  32.                 direction = self.forward
  33.             self.position = self.position + self.COMPASS[direction] * distance
  34.         return self
  35.  
  36.     def rotate(self, direction, distance):
  37.         self.rotations.rotate(self.ROTATION_DIRECTION[direction] * distance // 90)
  38.  
  39.     @property
  40.     def manhattan_distance(self):
  41.         return int(abs(self.position.real) + abs(self.position.imag))
  42.  
  43.     @property
  44.     def forward(self):
  45.         return self.rotations[0]
  46.  
  47.     def __str__(self):
  48.         ns_position = "N" if self.position.imag >= 0 else "S"
  49.         ew_position = "E" if self.position.real >= 0 else "W"
  50.         return (
  51.             f"{ns_position} {self.position.imag}, "
  52.             f"{ew_position} {self.position.real}, "
  53.             f"facing {self.forward}, "
  54.             f"Manhattan distance: {self.manhattan_distance}"
  55.         )
  56.  
  57.  
  58. class WaypointShipNavigation(ShipNavigation):
  59.     def __init__(
  60.         self,
  61.         waypoint_position=complex(10, 1),
  62.     ):
  63.         super().__init__(waypoint_position)
  64.         self.ship = ShipNavigation()
  65.         self.offset = None
  66.         self.update_offset()
  67.  
  68.     def __add__(self, direction_distance):
  69.         direction, distance = direction_distance
  70.         if direction in "NESW":
  71.             super().__add__(direction_distance)
  72.             self.update_offset()
  73.         elif direction in "RL":
  74.             for i in range(distance // 90):
  75.                 x = self.offset.real
  76.                 y = self.offset.imag
  77.                 if direction == "R":
  78.                     self.offset = complex(y, -x)
  79.                 else:
  80.                     self.offset = complex(-y, x)
  81.                 self.position = self.ship.position + self.offset
  82.         else:  # "F"
  83.             self.ship.position += distance * self.offset
  84.             self.position = self.ship.position + self.offset
  85.         return self
  86.  
  87.     def update_offset(self):
  88.         self.offset = self.position - self.ship.position
  89.  
  90.  
  91. def part_a(file_location) -> int:
  92.     navigation_instructions = direction_io(file_location)
  93.     current_position = ShipNavigation()
  94.     for direction_and_distance in navigation_instructions:
  95.         current_position += direction_and_distance
  96.     return current_position.manhattan_distance
  97.  
  98.  
  99. def part_b(file_location) -> int:
  100.     navigation_instructions = direction_io(file_location)
  101.     waypoint = WaypointShipNavigation()
  102.     for direction_and_distance in navigation_instructions:
  103.         waypoint += direction_and_distance
  104.     return waypoint.ship.manhattan_distance
  105.  
  106.  
  107. if __name__ == "__main__":
  108.     file_location = r"data\day12.txt"
  109.     print(part_a(file_location))
  110.     print(part_b(file_location))
  111.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement