diff options
| -rw-r--r-- | day15/__init__.py | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/day15/__init__.py b/day15/__init__.py index 38bef35..7b580d9 100644 --- a/day15/__init__.py +++ b/day15/__init__.py | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | import re | 2 | import re |
| 3 | from abc import ABC | 3 | from abc import ABC |
| 4 | from dataclasses import dataclass, field | 4 | from dataclasses import dataclass, field |
| 5 | from typing import Union | ||
| 6 | from typing import Tuple, Iterator, Set, List | 5 | from typing import Tuple, Iterator, Set, List |
| 6 | from typing import Union | ||
| 7 | 7 | ||
| 8 | from aoc import BaseAssignment | 8 | from aoc import BaseAssignment |
| 9 | from aoc.datastructures import Coordinate | 9 | from aoc.datastructures import Coordinate |
| @@ -25,7 +25,9 @@ class Sensor: | |||
| 25 | distance = self.coordinate.manhattan_distance(coordinate) | 25 | distance = self.coordinate.manhattan_distance(coordinate) |
| 26 | return distance <= self.radius | 26 | return distance <= self.radius |
| 27 | 27 | ||
| 28 | def x_coordinates_within_radius_at(self, y: int, map: "Map") -> Union[range, list]: | 28 | def x_coordinates_within_radius_at( |
| 29 | self, y: int, min_x: int = None, max_x: int = None | ||
| 30 | ) -> Union[range, list]: | ||
| 29 | 31 | ||
| 30 | coordinate = Coordinate(self.coordinate.x, y) | 32 | coordinate = Coordinate(self.coordinate.x, y) |
| 31 | 33 | ||
| @@ -35,11 +37,25 @@ class Sensor: | |||
| 35 | dy = abs(self.coordinate.y - y) | 37 | dy = abs(self.coordinate.y - y) |
| 36 | left_over = self.radius - dy | 38 | left_over = self.radius - dy |
| 37 | 39 | ||
| 40 | left_x = self.coordinate.x - left_over | ||
| 41 | right_x = self.coordinate.x + left_over | ||
| 42 | |||
| 38 | return range( | 43 | return range( |
| 39 | max(self.coordinate.x - left_over, map.width[0]), | 44 | max(left_x, min_x if min_x is not None else left_x - 1), |
| 40 | min(self.coordinate.x + left_over + 1, map.width[-1]), | 45 | min(right_x, max_x if max_x is not None else right_x + 1) + 1, |
| 41 | ) | 46 | ) |
| 42 | 47 | ||
| 48 | def area_inside(self) -> Set[Coordinate]: | ||
| 49 | coordinates = set() | ||
| 50 | |||
| 51 | for y in range( | ||
| 52 | self.coordinate.y - (self.radius - 1), self.coordinate.y + self.radius | ||
| 53 | ): | ||
| 54 | for x in self.x_coordinates_within_radius_at(y): | ||
| 55 | coordinates.add(Coordinate(x, y)) | ||
| 56 | |||
| 57 | return coordinates | ||
| 58 | |||
| 43 | 59 | ||
| 44 | @dataclass | 60 | @dataclass |
| 45 | class Map: | 61 | class Map: |
| @@ -98,7 +114,7 @@ class AssignmentOne(Assignment): | |||
| 98 | x_coordinates = { | 114 | x_coordinates = { |
| 99 | x | 115 | x |
| 100 | for sensor in map.sensors | 116 | for sensor in map.sensors |
| 101 | for x in sensor.x_coordinates_within_radius_at(y, map) | 117 | for x in sensor.x_coordinates_within_radius_at(y) |
| 102 | } | 118 | } |
| 103 | 119 | ||
| 104 | return len(x_coordinates) - len( | 120 | return len(x_coordinates) - len( |
| @@ -107,4 +123,18 @@ class AssignmentOne(Assignment): | |||
| 107 | 123 | ||
| 108 | 124 | ||
| 109 | class AssignmentTwo(Assignment): | 125 | class AssignmentTwo(Assignment): |
| 110 | pass | 126 | example_result = 56000011 |
| 127 | example_kwargs = {"max": 20} | ||
| 128 | |||
| 129 | def run(self, input: Iterator[Tuple[Sensor, Coordinate]], max=4000000): | ||
| 130 | map = self.create_map(input) | ||
| 131 | coordinates = {Coordinate(x, y) for x in range(max) for y in range(max)} | ||
| 132 | |||
| 133 | print("Coordinates generated") | ||
| 134 | |||
| 135 | for sensor in map.sensors: | ||
| 136 | coordinates -= sensor.area_inside() | ||
| 137 | |||
| 138 | distress_beacon = (coordinates - map.beacons).pop() | ||
| 139 | |||
| 140 | return (distress_beacon.x * 4000000) + distress_beacon.y | ||
