mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2025-09-05 23:00:38 +00:00
2024
This commit is contained in:
11
2024/04/findings.md
Normal file
11
2024/04/findings.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Day 4
|
||||
|
||||
## Part 1
|
||||
|
||||
I keep not learning. RTFM.
|
||||
|
||||
I started happily recursing into snakes of _XMAS_ letters, only to realise that only linear words are requested. Simple loop then.
|
||||
|
||||
## Part 2
|
||||
|
||||
Also quite easy. At first i messed up the cross, as i was checking for every angle, not only 45. And i had an error in the inverse of the direction of the cross, but nothing to hard.
|
130
2024/04/main.py
Normal file
130
2024/04/main.py
Normal file
@@ -0,0 +1,130 @@
|
||||
from typing import List, Union, Tuple
|
||||
|
||||
Point = Tuple[int]
|
||||
Path = Tuple[Point]
|
||||
Paths = [Path]
|
||||
|
||||
ALL_DIRECTIONS = (
|
||||
(1, 1),
|
||||
(1, 0),
|
||||
(1, -1),
|
||||
(0, 1),
|
||||
(0, -1),
|
||||
(-1, 1),
|
||||
(-1, 0),
|
||||
(-1, -1),
|
||||
)
|
||||
|
||||
LETTER_MAP = {"X": 0, "M": 1, "A": 2, "S": 3}
|
||||
|
||||
|
||||
class Board:
|
||||
rows: List[List[int]]
|
||||
|
||||
def __init__(self, rows: List[List[int]]):
|
||||
self.rows = rows
|
||||
self.max_y = len(self.rows)
|
||||
self.max_x = len(self.rows[0])
|
||||
|
||||
def get(self, x: int, y: int) -> Union[None, int]:
|
||||
if x < 0 or y < 0:
|
||||
return None
|
||||
if x >= self.max_x or y >= self.max_y:
|
||||
return None
|
||||
return self.rows[y][x]
|
||||
|
||||
# def get_neighbours(self, x: int, y: int, target: int) -> List[Point]:
|
||||
# n = []
|
||||
# for dx in range(x - 1, x + 2):
|
||||
# for dy in range(y - 1, y + 2):
|
||||
# if self.get(dx, dy) == target:
|
||||
# n.append((dx, dy))
|
||||
# return n
|
||||
|
||||
@staticmethod
|
||||
def parse(raw: str):
|
||||
rows = [[LETTER_MAP[letter] for letter in line] for line in raw.splitlines()]
|
||||
return Board(rows)
|
||||
|
||||
|
||||
# def find_maze(b: Board, path: Path, next_char: int) -> Paths:
|
||||
# x, y = path[-1]
|
||||
# print(f"Find {x} {y} n={next_char}")
|
||||
# paths: Paths = []
|
||||
# neighbours = b.get_neighbours(x, y, next_char)
|
||||
|
||||
# # Found last letter
|
||||
# if next_char == 3:
|
||||
# return [path + (n,) for n in neighbours]
|
||||
|
||||
# # Recurse
|
||||
# for n in neighbours:
|
||||
# p = path + (n,)
|
||||
# sub_paths = find(b, p, next_char + 1)
|
||||
# if len(sub_paths):
|
||||
# paths = paths + sub_paths
|
||||
|
||||
# return paths
|
||||
|
||||
|
||||
def find_line(b: Board, point: Point, direction: Point) -> Union[Path, None]:
|
||||
x, y = point
|
||||
dx, dy = direction
|
||||
path: Path = point
|
||||
for i in range(1, 4):
|
||||
px = x + (dx * i)
|
||||
py = y + (dy * i)
|
||||
if b.get(px, py) != i:
|
||||
return None
|
||||
path = path + ((x, y),)
|
||||
return path
|
||||
|
||||
|
||||
def find_x(b: Board, point: Point) -> bool:
|
||||
x, y = point
|
||||
for dx, dy in ALL_DIRECTIONS:
|
||||
# Check if is "M", then the opposite for "S" and the the perpendicular
|
||||
if b.get(x + dx, y + dy) == 1:
|
||||
if b.get(x - dx, y - dy) == 3:
|
||||
# Found first "MAS", check perpendicular
|
||||
p_dx = -dy
|
||||
p_dy = dx
|
||||
p_a = b.get(x + p_dx, y + p_dy)
|
||||
p_b = b.get(x - p_dx, y - p_dy)
|
||||
if (p_a == 1 and p_b == 3) or (p_a == 3 and p_b == 1):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def solve(raw: str) -> int:
|
||||
# Part 1
|
||||
part1 = []
|
||||
part2 = 0
|
||||
|
||||
b = Board.parse(raw)
|
||||
|
||||
for x in range(b.max_x):
|
||||
for y in range(b.max_y):
|
||||
p = b.get(x, y)
|
||||
if p == 0:
|
||||
for direction in ALL_DIRECTIONS:
|
||||
found = find_line(b, (x, y), direction)
|
||||
if found:
|
||||
part1.append(found)
|
||||
|
||||
if p == 2:
|
||||
if find_x(b, (x, y)):
|
||||
part2 += 1
|
||||
|
||||
return (len(part1), part2)
|
||||
|
||||
|
||||
# Test
|
||||
with open("./2024/04/test.txt", "r") as f:
|
||||
result = solve(f.read().strip())
|
||||
print(result)
|
||||
|
||||
# Input
|
||||
with open("./2024/04/input.txt", "r") as f:
|
||||
result = solve(f.read().strip())
|
||||
print(result)
|
Reference in New Issue
Block a user