-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathd10.py
More file actions
98 lines (73 loc) · 2.49 KB
/
d10.py
File metadata and controls
98 lines (73 loc) · 2.49 KB
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
import copy
from dataclasses import dataclass
import re
from day import Day, register_day
@register_day(2018, 10)
class Day10(Day):
def part_one(self) -> str:
sky = Sky(self.read_input())
sky.tick_until_aligned()
# print(sky) # The print is the answer
return "PHFZCEZX"
def part_two(self) -> str:
sky = Sky(self.read_input())
sky.tick_until_aligned()
return sky.seconds_elapsed.__str__()
PATTERN = re.compile(r"position=<(-?\d+),(-?\d+)>velocity=<(-?\d+),(-?\d+)>")
@dataclass
class Point:
x: int
y: int
vx: int
vy: int
class Sky:
points = []
original_points = []
seconds_elapsed = 0
def __init__(self, data: str):
for line in data.replace(" ", "").splitlines():
match = PATTERN.match(line)
self.original_points.append(
Point(
int(match.group(1)),
int(match.group(2)),
int(match.group(3)),
int(match.group(4)),
)
)
self.points = copy.deepcopy(self.original_points)
def height(self):
max_y = max([p.y for p in self.points])
min_y = min([p.y for p in self.points])
shift_y = -1 * max_y if max_y > 0 else abs(min_y)
return abs(min_y + shift_y)
def tick(self, back: bool = False):
modifier = -1 if back else 1
for point in self.points:
point.x += point.vx * modifier
point.y += point.vy * modifier
self.seconds_elapsed += 1 * modifier
def tick_until_aligned(self):
min_height = float("inf")
while True:
height = self.height()
if height <= min_height:
min_height = height
else:
self.tick(back=True)
break
self.tick()
def __repr__(self) -> str:
min_x = min([p.x for p in self.points])
max_x = max([p.x for p in self.points])
max_y = max([p.y for p in self.points])
min_y = min([p.y for p in self.points])
shift_x = abs(min_x) if min_x < 0 else (-1 * min_x)
shift_y = (-1 * max_y) if max_y > 0 else abs(max_y)
grid = []
for _ in range(abs(min_y + shift_y) + 1):
grid.append(["."] * (max_x + shift_x + 1))
for point in self.points:
grid[abs(point.y + shift_y)][point.x + shift_x] = "#"
grid.reverse()
return "\n".join(map(lambda row: "".join(row), grid))