Advent of Code 2024 - Day 4

# Part 1

 1from __future__ import annotations
 2
 3import collections
 4import dataclasses
 5
 6@dataclasses.dataclass
 7class TentativeMatch:
 8    desired_letter: str
 9    y: int
10    x: int
11    dy: int
12    dx: int
13
14def get_data():
15    data = []
16    with open("day_4_input.txt") as f:
17        for line in f:
18            data.append(line.strip())
19    return data
20
21def main(grid):
22    queue = collections.deque()
23    for y, row in enumerate(grid):
24        for x, _ in enumerate(row):
25            queue.append(TentativeMatch("X", y, x, 0, 0))
26
27    total = 0
28    while queue:
29        tm = queue.popleft()
30        if tm.y < 0 or tm.y >= len(grid):
31            continue
32        if tm.x < 0 or tm.x >= len(grid[0]):
33            continue
34
35        current_char = grid[tm.y][tm.x]
36
37        if current_char != tm.desired_letter:
38            continue
39
40        match current_char:
41            case 'X':
42                for dy, dx in [
43                        [-1, -1],
44                        [-1, 0],
45                        [-1, 1],
46                        [0, -1],
47                        [0, 1],
48                        [1, -1],
49                        [1, 0],
50                        [1, 1],
51                ]:
52                    queue.append(TentativeMatch("M", tm.y + dy, tm.x + dx, dy, dx))
53            case 'M':
54                queue.append(TentativeMatch("A", tm.y + tm.dy, tm.x + tm.dx, tm.dy, tm.dx))
55            case "A":
56                queue.append(TentativeMatch("S", tm.y + tm.dy, tm.x + tm.dx, tm.dy, tm.dx))
57            case "S":
58                total += 1
59            case _:
60                pass
61
62    return total
63
64
65if __name__ == "__main__":
66    print(f"{main(get_data()) = }")

# Part 2

 1from __future__ import annotations
 2
 3import collections
 4import dataclasses
 5
 6@dataclasses.dataclass
 7class TentativeMatch:
 8    desired_letter: str
 9    y: int
10    x: int
11
12def get_data():
13    data = []
14    with open("day_4_input_2.txt") as f:
15        for line in f:
16            data.append(line.strip())
17    return data
18
19def main(grid):
20    queue = collections.deque()
21    for y in range(1, len(grid) - 1):
22        for x in range(1, len(grid[0]) - 1):
23            queue.append(TentativeMatch("A", y, x))
24
25    total = 0
26    while queue:
27        tm = queue.popleft()
28
29        current_char = grid[tm.y][tm.x]
30
31        if current_char != tm.desired_letter:
32            continue
33
34        valid_1 = (grid[tm.y - 1][tm.x - 1], grid[tm.y + 1][tm.x + 1]) in [("M", "S"), ("S", "M")]
35        valid_2 = (grid[tm.y - 1][tm.x + 1], grid[tm.y + 1][tm.x - 1]) in [("M", "S"), ("S", "M")]
36
37        if valid_1 and valid_2:
38            total += 1
39
40    return total
41
42
43if __name__ == "__main__":
44    print(f"{main(get_data()) = }")