2024-12-16 07:54:23 +00:00
|
|
|
from typing import List, Tuple
|
|
|
|
|
|
|
|
EXAMPLE = """
|
|
|
|
MMMSXXMASM
|
|
|
|
MSAMXMSMSA
|
|
|
|
AMXSXMAAMM
|
|
|
|
MSAMASMSMX
|
|
|
|
XMASAMXAMM
|
|
|
|
XXAMMXXAMA
|
|
|
|
SMSMSASXSS
|
|
|
|
SAXAMASAAA
|
|
|
|
MAMMMXMMMM
|
|
|
|
MXMXAXMASX
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
class FindXMAS:
|
|
|
|
def __init__(self, input: str) -> None:
|
|
|
|
self.input = input
|
|
|
|
self.inputgrid = self._to_grid(self.input)
|
|
|
|
|
|
|
|
def __str__(self) -> str:
|
|
|
|
return f"Part1: {self._part1}\nPart2: {self._part2}"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _part1(self) -> int:
|
2024-12-22 13:59:30 +00:00
|
|
|
return len(self.locate_xmas())
|
2024-12-16 07:54:23 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def _part2(self) -> None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def _to_grid(input: str) -> List[List[str]]:
|
|
|
|
return [list(line) for line in input.splitlines() if line]
|
|
|
|
|
2024-12-22 13:59:30 +00:00
|
|
|
def find_neighbours(
|
2024-12-17 07:02:32 +00:00
|
|
|
self,
|
|
|
|
origin: Tuple[int, int],
|
|
|
|
target: str = "XMAS",
|
2024-12-22 13:59:30 +00:00
|
|
|
) -> List[Tuple[Tuple[int, ...]]]:
|
|
|
|
locations: List[Tuple[Tuple[int, ...]]] = []
|
|
|
|
x, y = origin
|
|
|
|
if self.inputgrid[x][y].upper() != target[0].upper():
|
|
|
|
return []
|
|
|
|
for dx in range(-1, 2):
|
|
|
|
for dy in range(-1, 2):
|
|
|
|
if dx == 0 and dy == 0:
|
2024-12-17 07:02:32 +00:00
|
|
|
continue
|
2024-12-22 13:59:30 +00:00
|
|
|
current = [(x, y)]
|
|
|
|
for n in range(1, len(target)):
|
|
|
|
nx = x + (n * dx)
|
|
|
|
ny = y + (n * dy)
|
|
|
|
if nx < 0 or ny < 0:
|
|
|
|
continue
|
|
|
|
try:
|
|
|
|
if self.inputgrid[nx][ny].upper() == target[n].upper():
|
|
|
|
current.append((nx, ny))
|
|
|
|
except IndexError:
|
|
|
|
pass
|
|
|
|
if len(current) == 4:
|
|
|
|
locations.append(tuple(current))
|
|
|
|
return locations
|
2024-12-17 07:02:32 +00:00
|
|
|
|
2024-12-22 13:59:30 +00:00
|
|
|
def locate_xmas(self) -> List[Tuple[Tuple[int, ...]]]:
|
|
|
|
locations: List[Tuple[Tuple[int, ...]]] = []
|
2024-12-17 07:02:32 +00:00
|
|
|
|
2024-12-16 07:54:23 +00:00
|
|
|
for i, line in enumerate(self.inputgrid):
|
|
|
|
for j, char in enumerate(line):
|
|
|
|
if char.upper() == "X":
|
2024-12-22 13:59:30 +00:00
|
|
|
neighbours = self.find_neighbours((i, j), target="XMAS")
|
|
|
|
if neighbours is None:
|
|
|
|
continue
|
|
|
|
locations = [*locations, *neighbours]
|
2024-12-16 07:54:23 +00:00
|
|
|
|
2024-12-22 13:59:30 +00:00
|
|
|
return locations
|
2024-12-16 07:54:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
example = FindXMAS(EXAMPLE)
|
2024-12-22 13:59:30 +00:00
|
|
|
print(example)
|
|
|
|
assert example._part1 == 18
|
|
|
|
with open("input.txt", "r") as f:
|
|
|
|
puzzle = FindXMAS(f.read())
|
|
|
|
print(puzzle)
|