adventofcode/2020/12/main.py
2020-12-14 15:26:16 +01:00

130 lines
2.8 KiB
Python

import math
class Waypoint:
def __init__(self):
self.heading = 90 # east
self.pos_north = 0
self.pos_east = 0
self.commands = {
"N": self.move_north,
"S": self.move_south,
"E": self.move_east,
"W": self.move_west,
"L": self.rotate_left,
"R": self.rotate_right,
"F": self.move_forward,
}
def load(self, filename):
with open(filename, "r", encoding="utf-8") as f:
for line in f:
data = line.rstrip()
self.process(data)
def move_north(self, value):
self.pos_north += value
def move_south(self, value):
self.pos_north -= value
def move_east(self, value):
self.pos_east += value
def move_west(self, value):
self.pos_east -= value
def rotate_left(self, degrees):
self.heading -= degrees
self.__fix_heading()
def rotate_right(self, degrees):
self.heading += degrees
self.__fix_heading()
def move_forward(self, value):
if self.heading == 0:
self.pos_north += value
elif self.heading == 90:
self.pos_east += value
elif self.heading == 180:
self.pos_north -= value
elif self.heading == 270:
self.pos_east -= value
else:
raise Exception(self.heading)
def __fix_heading(self):
while self.heading < 0:
self.heading += 360
while self.heading >= 360:
self.heading -= 360
def process(self, input):
cchar = input[:1]
value = int(input[1:])
command = self.commands[cchar]
command(value)
def get_md(self):
return abs(self.pos_east) + abs(self.pos_north)
class Ship:
def __init__(self):
self.waypoint = Waypoint()
self.pos_north = 0
self.pos_east = 0
self.commands = {
"F": self.move_forward,
"L": self.rotate_left,
"R": self.rotate_right,
}
def load(self, filename):
with open(filename, "r", encoding="utf-8") as f:
for line in f:
data = line.rstrip()
self.process(data)
def process(self, input):
cchar = input[:1]
value = int(input[1:])
if cchar in self.commands:
command = self.commands[cchar]
command(value)
else:
self.waypoint.process(input)
def move_forward(self, value):
self.pos_north += self.waypoint.pos_north * value
self.pos_east += self.waypoint.pos_east * value
def rotate_right(self, degrees):
self.rotate_left(-degrees)
def rotate_left(self, degrees):
radians = degrees / 180 * math.pi
c = math.cos(radians)
s = math.sin(radians)
e = c * self.waypoint.pos_east - s * self.waypoint.pos_north
n = s * self.waypoint.pos_east + c * self.waypoint.pos_north
self.waypoint.pos_east = round(e)
self.waypoint.pos_north = round(n)
def get_md(self):
return abs(self.pos_east) + abs(self.pos_north)
if __name__ == "__main__":
f = Waypoint()
f.load("data.txt")
md = f.get_md()
print(f"1: Manhattan distance is {md}")
f = Ship()
f.waypoint.pos_east = 10
f.waypoint.pos_north = 1
f.load("data.txt")
md = f.get_md()
print(f"2: Manhattan distance is {md}")