130 lines
2.8 KiB
Python
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}")
|