From 15ae5605806552f450b70474615b143d93585a0c Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Sat, 17 Dec 2022 14:29:46 +0100 Subject: Day 15 [WIP] --- day15/__init__.py | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'day15/__init__.py') diff --git a/day15/__init__.py b/day15/__init__.py index b43cae1..c22f0c1 100644 --- a/day15/__init__.py +++ b/day15/__init__.py @@ -3,20 +3,21 @@ import re from abc import ABC from collections import namedtuple from dataclasses import dataclass, field -from typing import Tuple, Iterator, Any, Set +from typing import Tuple, Iterator, Any, Set, Union from aoc import BaseAssignment class Coordinate(namedtuple("Coordinate", ["x", "y"])): def distance(self, other: "Coordinate"): - return abs(other.x - self.x) + abs(other.y - self.y) + return abs(self.x - other.x) + abs(self.y - other.y) @dataclass class Sensor: coordinate: Coordinate nearest: Coordinate + radius: int = None def __hash__(self): return hash(self.coordinate) @@ -24,6 +25,25 @@ class Sensor: def __post_init__(self): self.radius = self.coordinate.distance(self.nearest) + def within_radius(self, coordinate: Coordinate) -> bool: + distance = self.coordinate.distance(coordinate) + return distance <= self.radius + + def x_coordinates_within_radius_at(self, y: int, map: "Map") -> Union[range, list]: + + coordinate = Coordinate(self.coordinate.x, y) + + if not self.within_radius(coordinate): + return [] + + dy = abs(self.coordinate.y - y) + left_over = self.radius - dy + + return range( + max(self.coordinate.x - left_over, map.width[0]), + min(self.coordinate.x + left_over + 1, map.width[-1]), + ) + @dataclass class Map: @@ -77,21 +97,15 @@ class AssignmentOne(Assignment): def run(self, input: Iterator[Tuple[Sensor, Coordinate]], y=2000000): map = self.create_map(input) - no_sensor = 0 - - for x in map.width: - coordinate = Coordinate(x, y) - - for sensor in map.sensors: - if sensor.nearest == coordinate: - break - - distance = sensor.coordinate.distance(coordinate) - if distance <= sensor.radius: - no_sensor += 1 - break + x_coordinates = { + x + for sensor in map.sensors + for x in sensor.x_coordinates_within_radius_at(y, map) + } - return no_sensor + return len(x_coordinates) - len( + [beacon.x for beacon in map.beacons if beacon.y == y] + ) class AssignmentTwo(Assignment): -- cgit v1.2.3