Skip to content

Commit 3a80f80

Browse files
committed
AoC 2024 Day 21
1 parent d6020f7 commit 3a80f80

File tree

2 files changed

+39
-50
lines changed

2 files changed

+39
-50
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
## 2024
44

5-
![](https://img.shields.io/badge/stars%20⭐-40-yellow)
6-
![](https://img.shields.io/badge/days%20completed-20-red)
5+
![](https://img.shields.io/badge/stars%20⭐-42-yellow)
6+
![](https://img.shields.io/badge/days%20completed-21-red)
77

88
<!-- @BEGIN:ImplementationsTable:2024@ -->
99
| | 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 |
1010
| ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
11-
| python3 | [](src/main/python/AoC2024_01.py) | [](src/main/python/AoC2024_02.py) | [](src/main/python/AoC2024_03.py) | [](src/main/python/AoC2024_04.py) | [](src/main/python/AoC2024_05.py) | [](src/main/python/AoC2024_06.py) | [](src/main/python/AoC2024_07.py) | [](src/main/python/AoC2024_08.py) | [](src/main/python/AoC2024_09.py) | [](src/main/python/AoC2024_10.py) | [](src/main/python/AoC2024_11.py) | [](src/main/python/AoC2024_12.py) | [](src/main/python/AoC2024_13.py) | [](src/main/python/AoC2024_14.py) | [](src/main/python/AoC2024_15.py) | [](src/main/python/AoC2024_16.py) | [](src/main/python/AoC2024_17.py) | [](src/main/python/AoC2024_18.py) | [](src/main/python/AoC2024_19.py) | [](src/main/python/AoC2024_20.py) | | | | | |
11+
| python3 | [](src/main/python/AoC2024_01.py) | [](src/main/python/AoC2024_02.py) | [](src/main/python/AoC2024_03.py) | [](src/main/python/AoC2024_04.py) | [](src/main/python/AoC2024_05.py) | [](src/main/python/AoC2024_06.py) | [](src/main/python/AoC2024_07.py) | [](src/main/python/AoC2024_08.py) | [](src/main/python/AoC2024_09.py) | [](src/main/python/AoC2024_10.py) | [](src/main/python/AoC2024_11.py) | [](src/main/python/AoC2024_12.py) | [](src/main/python/AoC2024_13.py) | [](src/main/python/AoC2024_14.py) | [](src/main/python/AoC2024_15.py) | [](src/main/python/AoC2024_16.py) | [](src/main/python/AoC2024_17.py) | [](src/main/python/AoC2024_18.py) | [](src/main/python/AoC2024_19.py) | [](src/main/python/AoC2024_20.py) | [](src/main/python/AoC2024_21.py) | | | | |
1212
| java | [](src/main/java/AoC2024_01.java) | [](src/main/java/AoC2024_02.java) | [](src/main/java/AoC2024_03.java) | [](src/main/java/AoC2024_04.java) | [](src/main/java/AoC2024_05.java) | [](src/main/java/AoC2024_06.java) | [](src/main/java/AoC2024_07.java) | [](src/main/java/AoC2024_08.java) | | [](src/main/java/AoC2024_10.java) | [](src/main/java/AoC2024_11.java) | [](src/main/java/AoC2024_12.java) | | [](src/main/java/AoC2024_14.java) | [](src/main/java/AoC2024_15.java) | | | | | | | | | | |
1313
| rust | [](src/main/rust/AoC2024_01/src/main.rs) | [](src/main/rust/AoC2024_02/src/main.rs) | [](src/main/rust/AoC2024_03/src/main.rs) | [](src/main/rust/AoC2024_04/src/main.rs) | [](src/main/rust/AoC2024_05/src/main.rs) | [](src/main/rust/AoC2024_06/src/main.rs) | [](src/main/rust/AoC2024_07/src/main.rs) | [](src/main/rust/AoC2024_08/src/main.rs) | | [](src/main/rust/AoC2024_10/src/main.rs) | [](src/main/rust/AoC2024_11/src/main.rs) | [](src/main/rust/AoC2024_12/src/main.rs) | [](src/main/rust/AoC2024_13/src/main.rs) | [](src/main/rust/AoC2024_14/src/main.rs) | [](src/main/rust/AoC2024_15/src/main.rs) | [](src/main/rust/AoC2024_16/src/main.rs) | [](src/main/rust/AoC2024_17/src/main.rs) | [](src/main/rust/AoC2024_18/src/main.rs) | [](src/main/rust/AoC2024_19/src/main.rs) | | | | | | |
1414
<!-- @END:ImplementationsTable:2024@ -->

src/main/python/AoC2024_21.py

Lines changed: 36 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
import itertools
77
import sys
8+
from functools import cache
89

910
from aoc.common import InputData
1011
from aoc.common import SolutionBase
1112
from aoc.common import aoc_samples
12-
from aoc.common import log
1313
from aoc.graph import Dijkstra
1414
from aoc.grid import Cell
1515

@@ -32,34 +32,34 @@
3232
">": [["v"]],
3333
"v": [["<", "v"], ["v", "<"]],
3434
"<": [["v", "<", "<"], ["<", "v", "<"]],
35-
"A": [[""]],
35+
"A": [],
3636
},
3737
"^": {
38-
"^": [[""]],
38+
"^": [],
3939
">": [["v", ">"], [">", "v"]],
4040
"v": [["v"]],
4141
"<": [["v", "<"]],
4242
"A": [[">"]],
4343
},
4444
">": {
4545
"^": [["<", "^"], ["^", "<"]],
46-
">": [[""]],
46+
">": [],
4747
"v": [["<"]],
4848
"<": [["<", "<"]],
4949
"A": [["^"]],
5050
},
5151
"v": {
5252
"^": [["^"]],
5353
">": [[">"]],
54-
"v": [[""]],
54+
"v": [],
5555
"<": [["<"]],
5656
"A": [[">", "^"], ["^", ">"]],
5757
},
5858
"<": {
5959
"^": [[">", "^"]],
6060
">": [[">", ">"]],
6161
"v": [[">"]],
62-
"<": [[""]],
62+
"<": [],
6363
"A": [[">", ">", "^"], [">", "^", ">"]],
6464
},
6565
}
@@ -83,24 +83,29 @@ class Solution(SolutionBase[Input, Output1, Output2]):
8383
def parse_input(self, input_data: InputData) -> Input:
8484
return input_data
8585

86-
def do_dir_keypad(self, seq: list[str]) -> list[list[str]]:
87-
ans = []
88-
89-
def dfs(seq: list[str], pos: int, path: list[str]) -> None:
90-
if pos == len(seq):
91-
ans.append(path)
92-
return
93-
prev, nxt = seq[pos - 1], seq[pos]
94-
for s in DIR_KEYPAD[prev][nxt]:
95-
new_path = path[:]
96-
if s != [""]:
97-
for x in s:
98-
new_path.append(x)
99-
new_path.append("A")
100-
dfs(seq, pos + 1, new_path)
101-
102-
dfs(["A"] + seq, 1, [])
103-
return ans
86+
@cache
87+
def do_dir_keypad(self, seq: tuple[str, ...], level: int) -> int:
88+
assert len(seq) > 0
89+
if level == 1:
90+
ans = 0
91+
for first, second in zip(("A",) + seq, seq):
92+
moves = DIR_KEYPAD[first][second]
93+
ans += 1 if len(moves) == 0 else len(moves[0] + ["A"])
94+
return ans
95+
else:
96+
ans = 0
97+
for first, second in zip(("A",) + seq, seq):
98+
moves = DIR_KEYPAD[first][second]
99+
if len(moves) > 0:
100+
ans += min(
101+
self.do_dir_keypad(
102+
tuple(_ for _ in move + ["A"]), level - 1
103+
)
104+
for move in moves
105+
)
106+
else:
107+
ans += self.do_dir_keypad(("A",), level - 1)
108+
return ans
104109

105110
def do_num_keypad(self, seq: str) -> list[list[str]]:
106111
lst = [_ for _ in seq]
@@ -120,7 +125,6 @@ def do_num_keypad(self, seq: str) -> list[list[str]]:
120125
),
121126
lambda curr, nxt: 1,
122127
)
123-
# log((prev, nxt))
124128
paths = result.get_paths(end)
125129
moves = []
126130
for path in paths:
@@ -130,45 +134,30 @@ def do_num_keypad(self, seq: str) -> list[list[str]]:
130134
moves.append(move)
131135
all_moves.append(moves)
132136

133-
# log(all_moves)
134137
tmp = [p for p in itertools.product(*all_moves)]
135-
# log(tmp)
136138
for t in tmp:
137139
a = []
138140
for tt in t:
139141
x = list(tt) + ["A"]
140142
a.extend(x)
141143
if a is not None:
142144
ans.append(a) # type:ignore
143-
log(seq)
144-
log(ans)
145145
return ans
146146

147-
def solve_1(self, input: str) -> int:
147+
def solve(self, input: str, levels: int) -> int:
148148
best = sys.maxsize
149149
seqs = self.do_num_keypad(input)
150-
for seq1 in seqs:
151-
seq2 = self.do_dir_keypad(seq1)
152-
seq3 = []
153-
for seq in seq2:
154-
seq3.extend(self.do_dir_keypad(seq))
155-
shortest = sorted(seq3, key=len)[0]
156-
if len(shortest) < best:
157-
best = len(shortest)
150+
for seq in seqs:
151+
best = min(best, self.do_dir_keypad(tuple(_ for _ in seq), levels))
158152
return best
159153

160154
def part_1(self, input: Input) -> Output1:
161-
return sum(self.solve_1(combo) * int(combo[:-1]) for combo in input)
155+
return sum(self.solve(combo, 2) * int(combo[:-1]) for combo in input)
162156

163157
def part_2(self, input: Input) -> Output2:
164-
return 0
165-
166-
@aoc_samples(
167-
(
168-
("part_1", TEST, 126384),
169-
# ("part_2", TEST, "TODO"),
170-
)
171-
)
158+
return sum(self.solve(combo, 25) * int(combo[:-1]) for combo in input)
159+
160+
@aoc_samples((("part_1", TEST, 126384),))
172161
def samples(self) -> None:
173162
pass
174163

0 commit comments

Comments
 (0)