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
|
# -*- 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)
|