-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_02.py
121 lines (94 loc) · 3.62 KB
/
day_02.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from copy import deepcopy
from dataclasses import dataclass
from enum import Enum, auto
from typing import Generic, Callable
from typing import TypeVar
T = TypeVar('T')
class Direction(Enum):
FORWARD = auto(),
DOWN = auto(),
UP = auto(),
@dataclass
class Instruction:
direction: Direction
amount: int
def __iter__(self):
return iter((self.direction, self.amount))
lines = list(map(lambda x: Instruction(Direction[x[0].upper()], int(x[1])),
[distance.strip().split(' ') for distance in open("inputs/day_02.txt", "r").readlines()]))
class Navigator(Generic[T]):
def __init__(
self,
initial_ship_data: T,
operations: dict[Direction, Callable[[T, int], T]],
calc_position: Callable[[T], int]
) -> None:
super().__init__()
self.initial_ship_data = initial_ship_data
self.operations = operations
self.calc_position = calc_position
def navigate(self, instructions: list[Instruction]) -> int:
cur_ship_data = deepcopy(self.initial_ship_data)
for direction, amount in instructions:
cur_ship_data = self.operations[direction](cur_ship_data, amount)
return self.calc_position(cur_ship_data)
@dataclass
class BasicData:
position: int
depth: int
class NavigatorPart01(Navigator[BasicData]):
def __init__(self) -> None:
super().__init__(
BasicData(position=0, depth=0),
{
Direction.FORWARD: lambda data, amount: BasicData(position=data.position + amount, depth=data.depth),
Direction.DOWN: lambda data, amount: BasicData(position=data.position, depth=data.depth + amount),
Direction.UP: lambda data, amount: BasicData(position=data.position, depth=data.depth - amount),
},
lambda d: d.position * d.depth
)
@dataclass
class AngleData(BasicData):
aim: int
class NavigatorPart02(Navigator[BasicData]):
def __init__(self) -> None:
super().__init__(
AngleData(position=0, depth=0, aim=0),
{
Direction.FORWARD: lambda data, amount: AngleData(position=data.position + amount, depth=data.depth + data.aim * amount, aim=data.aim),
Direction.DOWN: lambda data, amount: AngleData(position=data.position, depth=data.depth, aim=data.aim + amount),
Direction.UP: lambda data, amount: AngleData(position=data.position, depth=data.depth, aim=data.aim - amount),
},
lambda d: d.position * d.depth
)
def part01(instructions: list[Instruction]):
position = 0
depth = 0
for direction, amount in instructions:
match direction:
case Direction.FORWARD:
position = position + amount
case Direction.DOWN:
depth = depth + amount
case Direction.UP:
depth = depth - amount
return position * depth
def part02(instructions: list[Instruction]):
position = 0
depth = 0
aim = 0
for direction, amount in instructions:
match direction:
case Direction.FORWARD:
position = position + amount
depth = depth + aim * amount
case Direction.DOWN:
aim = aim + amount
case Direction.UP:
aim = aim - amount
return position * depth
if __name__ == '__main__':
print(f"Part01_basic:\t {part01(lines)}")
print(f"Part01_generic:\t {NavigatorPart01().navigate(lines)}")
print(f"Part02_basic:\t {part02(lines)}")
print(f"Part02_generic:\t {NavigatorPart02().navigate(lines)}")