# -*- coding: utf-8 -*- from abc import ABC from typing import Iterator from aoc import BaseAssignment, I, T from aoc.datastructures import Coordinate class Assignment(BaseAssignment, ABC): def parse_item(cls, item: str) -> Iterator[list[str]]: yield [c for c in item] @classmethod def check_accessible_coordinate( cls, field: list[list[str]], coordinate: Coordinate ) -> bool: neighbouring_roll_count = 0 for neighbor in coordinate.neighbours(): if neighbor.in_bounds(field) and field[neighbor.y][neighbor.x] == "@": neighbouring_roll_count += 1 return neighbouring_roll_count < 4 @classmethod def get_accessible_coordinates( cls, field: list[list[str]], coordinates: list[Coordinate] ) -> list[Coordinate]: accessible_coordinates = [] for coordinate in coordinates: if field[coordinate.y][coordinate.x] != "@": continue if cls.check_accessible_coordinate(field, coordinate): accessible_coordinates.append(coordinate) return accessible_coordinates class AssignmentOne(Assignment): example_result = 13 def run(self, input: Iterator[str]) -> int: field = [next(self.parse_item(i)) for i in input] coordinates = [ Coordinate(x, y) for y in range(len(field)) for x in range(len(field[y])) ] return len(self.get_accessible_coordinates(field, coordinates)) class AssignmentTwo(Assignment): example_result = 43 def run(self, input: Iterator[str]) -> int: field = [next(self.parse_item(i)) for i in input] coordinates = [ Coordinate(x, y) for y in range(len(field)) for x in range(len(field[y])) ] rolls_removed = 0 while True: accessible_coordinates = self.get_accessible_coordinates(field, coordinates) if len(accessible_coordinates) == 0: return rolls_removed for coordinate in accessible_coordinates: field[coordinate.y][coordinate.x] = "." rolls_removed += len(accessible_coordinates)