mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2024-11-17 18:40:29 +01:00
84 lines
2.2 KiB
Python
84 lines
2.2 KiB
Python
|
from os.path import join, dirname
|
||
|
from typing import List, Optional
|
||
|
from math import cos, sin, radians, atan2, degrees, sqrt
|
||
|
|
||
|
directions = {
|
||
|
'N': 0,
|
||
|
'E': 90,
|
||
|
'S': 180,
|
||
|
'W': 270,
|
||
|
}
|
||
|
|
||
|
|
||
|
class Ship:
|
||
|
|
||
|
def __init__(self, waypoint=False) -> None:
|
||
|
self.x: float = 0
|
||
|
self.y: float = 0
|
||
|
self.d: int = directions['E']
|
||
|
|
||
|
self.waypoint = waypoint
|
||
|
self.wx: float = 10
|
||
|
self.wy: float = 1
|
||
|
|
||
|
@property
|
||
|
def distance(self) -> int:
|
||
|
return round(abs(self.x) + abs(self.y))
|
||
|
|
||
|
def __str__(self) -> str:
|
||
|
return f'⛴ X={round(self.x)} Y={round(self.y)} 𒎓={round(self.d)}\t🏴☠️ X={round(self.wx)} Y={round(self.wy)}'
|
||
|
|
||
|
def navigate(self, amount: int, degree: Optional[int] = None) -> None:
|
||
|
if degree == None:
|
||
|
if self.waypoint:
|
||
|
self.x += self.wx * amount
|
||
|
self.y += self.wy * amount
|
||
|
return
|
||
|
degree = self.d
|
||
|
dx = amount * sin(radians(degree))
|
||
|
dy = amount * cos(radians(degree))
|
||
|
if self.waypoint:
|
||
|
self.wx += dx
|
||
|
self.wy += dy
|
||
|
else:
|
||
|
self.x += dx
|
||
|
self.y += dy
|
||
|
|
||
|
def move(self, instruction: str) -> None:
|
||
|
cmd: str = instruction[0]
|
||
|
amount: int = int(instruction[1:])
|
||
|
if cmd in directions:
|
||
|
self.navigate(amount, degree=directions[cmd])
|
||
|
elif cmd == 'F':
|
||
|
self.navigate(amount)
|
||
|
else:
|
||
|
diff = amount if cmd == 'R' else -amount
|
||
|
if self.waypoint:
|
||
|
size = sqrt(self.wx**2 + self.wy**2)
|
||
|
d = degrees(atan2(self.wy, self.wx))
|
||
|
d -= diff
|
||
|
self.wx = size * cos(radians(d))
|
||
|
self.wy = size * sin(radians(d))
|
||
|
else:
|
||
|
self.d = (self.d + diff) % 360
|
||
|
|
||
|
def follow(self, file: str) -> None:
|
||
|
instructions = file.strip().split('\n')
|
||
|
for instruction in instructions:
|
||
|
self.move(instruction)
|
||
|
|
||
|
|
||
|
data = join(dirname(__file__), '../data.txt')
|
||
|
with open(data) as f:
|
||
|
txt = f.read()
|
||
|
|
||
|
ship = Ship()
|
||
|
ship.follow(txt)
|
||
|
print(ship)
|
||
|
print(ship.distance)
|
||
|
|
||
|
ship = Ship(waypoint=True)
|
||
|
ship.follow(txt)
|
||
|
print(ship)
|
||
|
print(ship.distance)
|