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}")