Skip to content

Commit ceb3d96

Browse files
committed
[Day 20] Optimize
1 parent 96d8bb6 commit ceb3d96

File tree

2 files changed

+44
-33
lines changed

2 files changed

+44
-33
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ This Julia package contains my solutions for [Advent of Code 2024](https://adven
2929
| 17 | [:white_check_mark:](https://adventofcode.com/2024/day/17) | 6.921 ms | 706.30 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day17.jl) |
3030
| 18 | [:white_check_mark:](https://adventofcode.com/2024/day/18) | 3.007 ms | 5.51 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) | 57.908 ms | 3.41 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day19.jl) |
32-
| 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) |
32+
| 20 | [:white_check_mark:](https://adventofcode.com/2024/day/20) | 49.638 ms | 701.11 KiB| [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day20.jl) |
3333
| 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) |
3434
| 22 | [:white_check_mark:](https://adventofcode.com/2024/day/22) | 25.522 ms | 1.18 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day22.jl) |
3535
| 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) |

src/day20.jl

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,76 @@
11
module Day20
22

33
using AdventOfCode2024
4-
4+
using DataStructures
55

66
function day20(input::String = readInput(joinpath(@__DIR__, "..", "data", "day20.txt")))
7-
data = map(x -> x[1], reduce(vcat, permutedims.(map(x -> split(x, ""), split(input)))))
7+
data = stack(split(rstrip(input), '\n'))
88
tte = time_to_end(data)
99
return [count_cheats(tte, 100), count_cheats(tte, 100; max_time=20)]
1010
end
1111

1212
function time_to_end(data::Matrix{Char})
13-
tte = -1 * ones(Int, size(data)...)
14-
goal = findall(x -> x == 'E', data)[1]
15-
current = [goal]
16-
time = 0
17-
while !isempty(current)
18-
for elem current
19-
tte[elem] = time
20-
end
21-
next = Vector{CartesianIndex{2}}()
22-
while !isempty(current)
23-
elem = popfirst!(current)
24-
for neigh [elem + x for x CartesianIndex.((1,-1,0,0), (0,0,1,-1))]
25-
if data[neigh] != '#' && tte[neigh] == -1
26-
push!(next, neigh)
13+
rows, cols = size(data)
14+
tte = fill(-1, rows, cols)
15+
goal = findfirst(==('E'), data)
16+
queue = Deque{CartesianIndex{2}}()
17+
push!(queue, goal)
18+
tte[goal] = 0
19+
time = 1
20+
21+
while !isempty(queue)
22+
for _ in 1:length(queue)
23+
elem = popfirst!(queue)
24+
for dir in (CartesianIndex(-1, 0), CartesianIndex(1, 0), CartesianIndex(0, -1), CartesianIndex(0, 1))
25+
neigh = elem + dir
26+
if checkbounds(Bool, data, neigh) && data[neigh] != '#' && tte[neigh] == -1
27+
tte[neigh] = time
28+
push!(queue, neigh)
2729
end
2830
end
2931
end
30-
current = next
3132
time += 1
3233
end
3334
return tte
3435
end
3536

3637
function count_cheats(tte::Matrix{Int}, threshold::Int; max_time::Int=2)
38+
rows, cols = size(tte)
3739
count = 0
38-
for c findall(x -> x >= 0, tte)
39-
for e reachable_within(tte, c, max_time)
40-
time_saved = tte[e] < tte[c] ? tte[c] - tte[e] - sum(abs.((c-e).I)) : -1
41-
if time_saved >= threshold
42-
count += 1
40+
offsets = generate_offsets(max_time)
41+
42+
for c in findall(>=(0), tte)
43+
ci, cj = Tuple(c)
44+
tte_c = tte[c]
45+
46+
for (di, dj) in offsets
47+
ni, nj = ci + di, cj + dj
48+
if 1 <= ni <= rows && 1 <= nj <= cols
49+
e = CartesianIndex(ni, nj)
50+
if tte[e] >= 0 && tte[e] < tte_c
51+
time_saved = tte_c - tte[e] - (abs(di) + abs(dj))
52+
time_saved >= threshold && (count += 1)
53+
end
4354
end
4455
end
4556
end
4657
return count
4758
end
4859

49-
function reachable_within(tte::Matrix{Int}, c::CartesianIndex{2}, picoseconds::Int)
50-
reachable = Set{CartesianIndex{2}}()
51-
for p 1:picoseconds
52-
for i 0:p
53-
j = p - i
54-
for (s1, s2) zip((1, 1, -1, -1), (1, -1, 1, -1))
55-
n = CartesianIndex(c[1] + s1*i, c[2] + s2*j)
56-
if checkbounds(Bool, tte, n) && tte[n] >= 0
57-
push!(reachable, n)
60+
@inline function generate_offsets(max_dist::Int)
61+
offsets = Tuple{Int,Int}[]
62+
for d in 0:max_dist
63+
for i in 0:d
64+
j = d - i
65+
for s1 in (-1, 1)
66+
for s2 in (-1, 1)
67+
push!(offsets, (s1*i, s2*j))
5868
end
5969
end
6070
end
6171
end
62-
return reachable
72+
unique!(offsets)
73+
return offsets
6374
end
6475

6576
end # module

0 commit comments

Comments
 (0)