This repository has been archived by the owner on Dec 31, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
__init__.py
76 lines (64 loc) · 2.61 KB
/
__init__.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
"""--- Day 5: Hydrothermal Venture ---"""
from dataclasses import dataclass
from operator import add
from operator import sub
from pathlib import Path
from aoc import open_utf8
@dataclass
class Point:
"""Cartesian point that also stores value data."""
x: int
y: int
value_hv: int = 0
value_d: int = 0
@dataclass
class Vent:
"""Linear volcanic Vent defined by two points."""
p1: Point
p2: Point
def compute_cartesian_points(self) -> {str: Point}:
"""Compute the points crossed by the line in the vent.
:return: Dictionary of 'x,y' keys to populated Point values.
"""
run = self.p2.x - self.p1.x # how far we move in the x dimension
rise = self.p2.y - self.p1.y # how far we move in the y dimension
run_op = add if run > 0 else sub # polarity of x movement
rise_op = add if rise > 0 else sub # polarity of y movement
steps = range((abs(run) if abs(run) > 0 else abs(rise)) + 1)
return {
f"{run_op(self.p1.x, step if abs(run) else 0)},"
f"{rise_op(self.p1.y, step if abs(rise) else 0)}": Point(
run_op(self.p1.x, step if abs(run) else 0),
rise_op(self.p1.y, step if abs(rise) else 0),
value_hv=1 if rise == 0 or run == 0 else 0,
value_d=1 if rise != 0 and run != 0 else 0,
)
for step in steps
}
def load_dataset(dataset_path: Path) -> {str: Point}:
"""Loads the vents from file, returns a list of cartesian points.
:param dataset_path: Path object to load the data from.
:return: Dictionary of 'x,y' keys with populated Point values.
"""
data = {}
with open_utf8(dataset_path) as file:
for line in file:
if len(line.strip()) > 1:
vent = Vent(
Point(
int(line.split(" -> ")[0].split(",")[0].strip()),
int(line.split(" -> ")[0].split(",")[1].strip()),
),
Point(
int(line.split(" -> ")[1].split(",")[0].strip()),
int(line.split(" -> ")[1].split(",")[1].strip()),
),
)
points = vent.compute_cartesian_points()
for point in points:
if point in data: # Multiple
data[point].value_hv += points[point].value_hv
data[point].value_d += points[point].value_d
else: # Add the point to the global dataset
data[point] = points[point]
return data