Skip to content

Commit 64dde16

Browse files
committed
[Day 21] Add solution
1 parent e02dabc commit 64dde16

File tree

5 files changed

+77
-103
lines changed

5 files changed

+77
-103
lines changed

Manifest.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
julia_version = "1.11.2"
44
manifest_format = "2.0"
5-
project_hash = "a1b4ea60f75de15929aad726e8406053b9d7159e"
5+
project_hash = "de21728373435a74a0063d7145395fc5e7638053"
66

77
[[deps.Artifacts]]
88
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
@@ -73,11 +73,22 @@ version = "1.11.0"
7373
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
7474
version = "1.11.0"
7575

76+
[[deps.MacroTools]]
77+
git-tree-sha1 = "72aebe0b5051e5143a079a4685a46da330a40472"
78+
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
79+
version = "0.5.15"
80+
7681
[[deps.Markdown]]
7782
deps = ["Base64"]
7883
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
7984
version = "1.11.0"
8085

86+
[[deps.Memoize]]
87+
deps = ["MacroTools"]
88+
git-tree-sha1 = "2b1dfcba103de714d31c033b5dacc2e4a12c7caa"
89+
uuid = "c03570c3-d221-55d1-a50c-7939bbd78826"
90+
version = "0.4.4"
91+
8192
[[deps.Mmap]]
8293
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
8394
version = "1.11.0"

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
88
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
99
IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
1010
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
11+
Memoize = "c03570c3-d221-55d1-a50c-7939bbd78826"
1112
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1213

1314
[compat]
1415
BenchmarkTools = "1.5.0"
1516
DataStructures = "0.18.20"
1617
IterTools = "1.10.0"
1718
LinearAlgebra = "1.11.0"
19+
Memoize = "0.4.4"
1820
Printf = "1.11.0"
1921
julia = "1.6.7"
2022

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ This Julia package contains my solutions for [Advent of Code 2024](https://adven
3030
| 18 | [:white_check_mark:](https://adventofcode.com/2024/day/18) |2.964 ms | 5.64 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day18.jl) |
3131
| 19 | [:white_check_mark:](https://adventofcode.com/2024/day/19) | 59.678 ms | 3.41 MiB| [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day19.jl) |
3232
| 20 | [:white_check_mark:](https://adventofcode.com/2024/day/20) | 227.453 ms | 224.97 MiB| [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day20.jl) |
33+
| 21 | [:white_check_mark:](https://adventofcode.com/2024/day/21) | 296.609 μs | 78.89 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day21.jl) |
3334
| 22 | [:white_check_mark:](https://adventofcode.com/2024/day/22) | 241.724 ms | 78.80 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day22.jl) |
3435
| 23 | [:white_check_mark:](https://adventofcode.com/2024/day/23) | 4.197 ms | 3.82 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day23.jl) |
3536
| 24 | [:white_check_mark:](https://adventofcode.com/2024/day/24) | 5.658 s | 3.28 GiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day24.jl) |
36-
<!-- | 21 | [:white_check_mark:](https://adventofcode.com/2024/day/21) | 9.675 ms | 7.19 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day21.jl) | -->
3737
<!-- | 25 | [:white_check_mark:](https://adventofcode.com/2024/day/25) | 69.476 ms | 62.03 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day25.jl) | -->
3838

3939

src/day21.jl

Lines changed: 52 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,68 @@
11
module Day21
22

33
using AdventOfCode2024
4-
4+
using Memoize
55

66
function day21(input::String = readInput(joinpath(@__DIR__, "..", "data", "day21.txt")))
7-
numerical_keypad = ['#' '#' '#' '#' '#';
8-
'#' '7' '8' '9' '#';
9-
'#' '4' '5' '6' '#';
10-
'#' '1' '2' '3' '#';
11-
'#' '.' '0' 'A' '#';
12-
'#' '#' '#' '#' '#']
13-
directional_keypad = ['#' '#' '#' '#' '#';
14-
'#' '.' '^' 'A' '#';
15-
'#' '<' 'v' '>' '#';
16-
'#' '#' '#' '#' '#']
17-
layer1 = generate_instructions("029A", numerical_keypad)
18-
layer2 = reduce(vcat, [generate_instructions(x, directional_keypad) for x layer1])
19-
end
20-
21-
# function calculate_instructions(keypad::Matrix{Char}, from::Char, to::Char)
22-
# start = findall(x -> x == from, keypad)[1]
23-
# goal = findall(x -> x == to, keypad)[1]
24-
# dirs = (('v', [1, 0]), ('^', [-1, 0]), ('>', [0, 1]), ('<', [0, -1]))
25-
# visited = zeros(Bool, size(keypad)...)
26-
# current = [(start, "")]
27-
# while !isempty(current)
28-
# for (elem, st) ∈ current
29-
# if elem == goal
30-
# return st
31-
# end
32-
# visited[elem] = true
33-
# end
34-
# new_current = []
35-
# while !isempty(current)
36-
# elem, st = pop!(current)
37-
# for (c, dir) ∈ dirs
38-
# neighcoord = CartesianIndex((elem.I .+ dir)...)
39-
# if keypad[neighcoord] != '#' && !visited[neighcoord]
40-
# push!(new_current, (neighcoord, st * c))
41-
# end
42-
# end
43-
# end
44-
# current = new_current
45-
# end
46-
# end
47-
48-
function from_to(keypad::Matrix{Char}, from::Char, to::Char)
49-
start = findall(x -> x == from, keypad)[1]
50-
goal = findall(x -> x == to, keypad)[1]
51-
# dirs = (('v', [1, 0]), ('^', [-1, 0]), ('>', [0, 1]), ('<', [0, -1]))
7+
data = split(rstrip(input), "\n")
8+
numpad = Dict{Char,Tuple{Int,Int}}(
9+
'A' => (4, 3),
10+
'0' => (4, 2),
11+
'1' => (3, 1),
12+
'2' => (3, 2),
13+
'3' => (3, 3),
14+
'4' => (2, 1),
15+
'5' => (2, 2),
16+
'6' => (2, 3),
17+
'7' => (1, 1),
18+
'8' => (1, 2),
19+
'9' => (1, 3)
20+
)
21+
dirpad = Dict{Char,Tuple{Int,Int}}(
22+
'A' => (1, 3),
23+
'^' => (1, 2),
24+
'<' => (2, 1),
25+
'v' => (2, 2),
26+
'>' => (2, 3)
27+
)
28+
numpad_graph = create_graph(numpad, (4, 1))
29+
dirpad_graph = create_graph(dirpad, (1, 1))
5230

53-
diff = goal - start
54-
if diff[1] >= 0
55-
x = 'v'
56-
else
57-
x = '^'
31+
p1, p2 = 0, 0
32+
for d data
33+
p1 += solve(d, 3, numpad_graph, dirpad_graph, true) * parse(Int, d[1:end-1])
34+
p2 += solve(d, 26, numpad_graph, dirpad_graph, true) * parse(Int, d[1:end-1])
5835
end
59-
if diff[2] > 0
60-
y = '>'
61-
else
62-
y = '<'
63-
end
64-
return unique([repeat(x, abs(diff[1])) * repeat(y, abs(diff[2])), repeat(y, abs(diff[2])) * repeat(x, abs(diff[1]))])
36+
return [p1, p2]
6537
end
6638

67-
# function code_numerical(code::String, keypad::Matrix{Char})
68-
# instructions = ""
69-
# from = 'A'
70-
# for to ∈ code
71-
# instructions *= calculate_instructions(keypad, from, to) * 'A'
72-
# from = to
73-
# end
74-
# return instructions
75-
# end
76-
77-
# function code_directional(code::String, keypad::Matrix{Char})
78-
79-
# end
80-
81-
# function generate_instructions(code::String, keypad::Matrix{Char})
82-
# instructions = ""
83-
# from = 'A'
84-
# for to ∈ code
85-
# instructions *= calculate_instructions(keypad, from, to) * 'A'
86-
# from = to
87-
# end
88-
# return instructions
89-
# end
90-
91-
function generate_instructions(code::String, keypad::Matrix{Char})
92-
instructions = Vector{String}()
93-
from = 'A'
94-
for to code
95-
parts = from_to(keypad, from, to)
96-
if isempty(instructions)
97-
for instr parts
98-
push!(instructions, instr * 'A')
99-
end
100-
end
101-
if length(parts) > 1
102-
cp = copy(instructions)
103-
end
104-
for (i, _) enumerate(instructions)
105-
instructions[i] *= parts[1] * 'A'
106-
end
107-
if length(parts) > 1
108-
for (i, _) enumerate(cp)
109-
push!(instructions, cp[i] * parts[2] * 'A')
39+
function create_graph(keypad, forbidden_coord)
40+
graph = Dict{Char,Dict{Char,String}}()
41+
for key keys(keypad)
42+
graph[key] = Dict{Char,String}()
43+
end
44+
for (k1, (x1, y1)) keypad
45+
for (k2, (x2, y2)) keypad
46+
path = repeat("<", max(0, y1-y2)) * repeat("v", max(0, x2-x1)) * repeat("^", max(0, x1-x2)) * repeat(">", max(0, y2-y1))
47+
if forbidden_coord == (x1, y2) || forbidden_coord == (x2, y1)
48+
path = reverse(path)
11049
end
50+
graph[k1][k2] = path * 'A'
11151
end
11252
end
113-
return instructions
53+
return graph
11454
end
11555

56+
@memoize function solve(sequence, iterations, numpad_graph, dirpad_graph, first)
57+
iterations == 0 && return length(sequence)
58+
prev = 'A'
59+
total = 0
60+
graph = first ? numpad_graph : dirpad_graph
61+
for c sequence
62+
total += solve(graph[prev][c], iterations - 1, numpad_graph, dirpad_graph, false)
63+
prev = c
64+
end
65+
return total
66+
end
11667

11768
end # module

test/runtests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,16 @@ end
328328
@testset AdventOfCode2024.Day20.day20() == [1411, 1010263]
329329
end
330330

331+
@testset "Day 21" begin
332+
sample = "029A\n" *
333+
"980A\n" *
334+
"179A\n" *
335+
"456A\n" *
336+
"379A\n"
337+
@testset AdventOfCode2024.Day21.day21(sample) == [126384, 154115708116294]
338+
@testset AdventOfCode2024.Day21.day21() == [163920, 204040805018350]
339+
end
340+
331341
@testset "Day 22" begin
332342
sample = "1\n" *
333343
"10\n" *

0 commit comments

Comments
 (0)