summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <t0m.vd.l33@gmail.com>2022-12-16 11:48:40 +0100
committerGravatar Tom van der Lee <t0m.vd.l33@gmail.com>2022-12-16 11:48:58 +0100
commitb37323ac00baa3ac5dcc042eaad95d4dc1eeab0f (patch)
treec9418cdf2bda2f0689e1919c6c4d9cc230675ee1
parentfa75898ed35c732ba4e9d455f16dee48ba6c5ca8 (diff)
download2022-b37323ac00baa3ac5dcc042eaad95d4dc1eeab0f.tar.gz
2022-b37323ac00baa3ac5dcc042eaad95d4dc1eeab0f.tar.bz2
2022-b37323ac00baa3ac5dcc042eaad95d4dc1eeab0f.zip
Day 15 [WIP]
-rw-r--r--aoc/__init__.py18
-rw-r--r--aoc/test_init.py4
-rw-r--r--day15/__init__.py60
3 files changed, 58 insertions, 24 deletions
diff --git a/aoc/__init__.py b/aoc/__init__.py
index 8368f7b..7a089f6 100644
--- a/aoc/__init__.py
+++ b/aoc/__init__.py
@@ -1,11 +1,15 @@
1# -*- coding: utf-8 -*- 1# -*- coding: utf-8 -*-
2import os 2import os
3from abc import ABC 3from abc import ABC
4from typing import Generator, Any, Iterator 4from typing import Generator, Any, Iterator, Dict, TypeVar, Generic
5 5
6T = TypeVar("T")
7I = TypeVar("I")
6 8
7class BaseAssignment(ABC): 9
8 example_result = NotImplemented 10class BaseAssignment(Generic[T, I], ABC):
11 example_result: T = NotImplemented
12 example_kwargs: Dict = {}
9 13
10 def __init__(self, path): 14 def __init__(self, path):
11 self.path = path 15 self.path = path
@@ -13,14 +17,14 @@ class BaseAssignment(ABC):
13 def __str__(self): 17 def __str__(self):
14 return f"{self.__module__}.{self.__class__.__name__}" 18 return f"{self.__module__}.{self.__class__.__name__}"
15 19
16 def parse_item(self, item: str) -> Any: 20 def parse_item(self, item: str) -> I:
17 return item 21 return item
18 22
19 @property 23 @property
20 def part(self): 24 def part(self) -> int:
21 return 1 if self.__class__.__name__.endswith("One") else 2 25 return 1 if self.__class__.__name__.endswith("One") else 2
22 26
23 def read_input(self, example=False) -> Generator: 27 def read_input(self, example=False) -> Iterator[I]:
24 file = f"{self.path}/input.txt" 28 file = f"{self.path}/input.txt"
25 29
26 if example or not os.path.isfile(file): 30 if example or not os.path.isfile(file):
@@ -35,5 +39,5 @@ class BaseAssignment(ABC):
35 for line in input_file.readlines(): 39 for line in input_file.readlines():
36 yield self.parse_item(line.strip("\n")) 40 yield self.parse_item(line.strip("\n"))
37 41
38 def run(self, input: Iterator) -> Any: 42 def run(self, input: Iterator[I]) -> T:
39 raise NotImplementedError("Please implement run") 43 raise NotImplementedError("Please implement run")
diff --git a/aoc/test_init.py b/aoc/test_init.py
index f804c41..e52daf7 100644
--- a/aoc/test_init.py
+++ b/aoc/test_init.py
@@ -1,6 +1,8 @@
1# -*- coding: utf-8 -*- 1# -*- coding: utf-8 -*-
2def test_assignment_examples(assignment): 2def test_assignment_examples(assignment):
3 assert ( 3 assert (
4 assignment.run(input=assignment.read_input(example=True)) 4 assignment.run(
5 input=assignment.read_input(example=True), **assignment.example_kwargs
6 )
5 == assignment.example_result 7 == assignment.example_result
6 ) 8 )
diff --git a/day15/__init__.py b/day15/__init__.py
index 3ba49d3..b43cae1 100644
--- a/day15/__init__.py
+++ b/day15/__init__.py
@@ -18,21 +18,35 @@ class Sensor:
18 coordinate: Coordinate 18 coordinate: Coordinate
19 nearest: Coordinate 19 nearest: Coordinate
20 20
21 def __hash__(self):
22 return hash(self.coordinate)
23
21 def __post_init__(self): 24 def __post_init__(self):
22 self.radius = self.coordinate.distance(self.nearest) 25 self.radius = self.coordinate.distance(self.nearest)
23 26
24 27
25@dataclass 28@dataclass
26class Map: 29class Map:
27 sensors: Set[Coordinate] = field(default_factory=set) 30 sensors: Set[Sensor] = field(default_factory=set)
28 beacons: Set[Coordinate] = field(default_factory=set) 31 beacons: Set[Coordinate] = field(default_factory=set)
29 32
33 def __post_init__(self):
34 all_coordinates = self.beacons | {sensor.coordinate for sensor in self.sensors}
35
36 min_x = min(c.x for c in all_coordinates)
37 max_x = max(c.x for c in all_coordinates)
38 min_y = min(c.y for c in all_coordinates)
39 max_y = max(c.y for c in all_coordinates)
40
41 self.width = list(range(min_x, max_x + 1))
42 self.height = list(range(min_y, max_y + 1))
43
30 44
31input_pattern = re.compile("x=(-?[-0-9]+), y=(-?[0-9]+)") 45input_pattern = re.compile("x=(-?[-0-9]+), y=(-?[0-9]+)")
32 46
33 47
34class Assignment(BaseAssignment, ABC): 48class Assignment(BaseAssignment[int, Tuple[Sensor, Coordinate]], ABC):
35 def get_coordinates(self, line: str) -> Tuple[Coordinate, Coordinate]: 49 def parse_item(self, line: str) -> Tuple[Sensor, Coordinate]:
36 match = input_pattern.findall(line) 50 match = input_pattern.findall(line)
37 51
38 if len(match) != 2: 52 if len(match) != 2:
@@ -43,27 +57,41 @@ class Assignment(BaseAssignment, ABC):
43 beacon = Coordinate(int(beacon_match[0]), int(beacon_match[1])) 57 beacon = Coordinate(int(beacon_match[0]), int(beacon_match[1]))
44 sensor = Sensor(Coordinate(int(sensor_match[0]), int(sensor_match[1])), beacon) 58 sensor = Sensor(Coordinate(int(sensor_match[0]), int(sensor_match[1])), beacon)
45 59
46 result = tuple(Coordinate(int(x), int(y)) for x, y in match) 60 return sensor, beacon
47 61
48 return result 62 def create_map(self, input: Iterator[Tuple[Sensor, Coordinate]]) -> Map:
63 sensors = set()
64 beacons = set()
49 65
50 def parse_input(self): 66 for sensor, beacon in input:
51 pass 67 sensors.add(sensor)
68 beacons.add(beacon)
69
70 return Map(sensors, beacons)
52 71
53 72
54class AssignmentOne(Assignment): 73class AssignmentOne(Assignment):
55 example_result = 10 74 example_result = 26
75 example_kwargs = {"y": 10}
56 76
57 def run(self, input: Iterator) -> Any: 77 def run(self, input: Iterator[Tuple[Sensor, Coordinate]], y=2000000):
58 sensors = set() 78 map = self.create_map(input)
59 beacons = set()
60 79
61 for line in input: 80 no_sensor = 0
62 sensor, beacon = self.get_coordinates(line) 81
63 sensors.add(sensor) 82 for x in map.width:
64 beacons.add(beacon) 83 coordinate = Coordinate(x, y)
84
85 for sensor in map.sensors:
86 if sensor.nearest == coordinate:
87 break
88
89 distance = sensor.coordinate.distance(coordinate)
90 if distance <= sensor.radius:
91 no_sensor += 1
92 break
65 93
66 pass 94 return no_sensor
67 95
68 96
69class AssignmentTwo(Assignment): 97class AssignmentTwo(Assignment):