@@ -4,55 +4,76 @@ using AdventOfCode2024
4
4
5
5
function day11 (input:: String = readInput (joinpath (@__DIR__ , " .." , " data" , " day11.txt" )))
6
6
data = parse .(Int, split (rstrip (input)))
7
- return [solve (data, 25 ), solve (data, 75 )]
8
- end
9
-
10
- function solve (data, runtime)
7
+ runtime1 = 25
8
+ runtime2 = 75
9
+
11
10
lookup = Dict {Int,Tuple{Int,Int}} ()
12
11
lookup[0 ] = (1 , - 1 )
13
- stones = Dict {Int,Dict{Int,Int}} ()
14
- for i ∈ 0 : runtime
15
- stones[i] = Dict {Int,Int} ()
12
+
13
+ stones = Vector {Dict{Int,Int}} (undef, runtime2 + 1 )
14
+ for i in 0 : runtime2
15
+ stones[i+ 1 ] = Dict {Int,Int} ()
16
16
end
17
- for value ∈ data
18
- stones[runtime][value] = 1
17
+
18
+ result1 = compute_stones! (stones, data, runtime1, lookup)
19
+ result2 = continue_stones! (stones, runtime1, runtime2, lookup)
20
+
21
+ return [result1, result2]
22
+ end
23
+
24
+ function compute_stones! (stones, data, runtime, lookup)
25
+ for value in data
26
+ stones[runtime+ 1 ][value] = get! (stones[runtime+ 1 ], value, 0 ) + 1
19
27
end
20
- @inbounds for rt ∈ runtime: - 1 : 1
21
- for stone ∈ keys (stones[rt])
22
- if haskey (lookup, stone)
23
- l, r = lookup[stone]
24
- else
25
- if iseven (length (digits (stone)))
26
- l, r = split_number (stone)
27
- else
28
- l, r = stone * 2024 , - 1
29
- end
30
- lookup[stone] = (l, r)
31
- end
32
- amount = stones[rt][stone]
33
- if haskey (stones[rt- 1 ], l)
34
- stones[rt- 1 ][l] += amount
35
- else
36
- stones[rt- 1 ][l] = amount
37
- end
38
- r == - 1 && continue
39
- if haskey (stones[rt- 1 ], r)
40
- stones[rt- 1 ][r] += amount
41
- else
42
- stones[rt- 1 ][r] = amount
43
- end
28
+
29
+ @inbounds for rt in runtime: - 1 : 1
30
+ current = stones[rt+ 1 ]
31
+ next = stones[rt]
32
+ for stone in keys (current)
33
+ l, r = get_transformation (stone, lookup)
34
+ amount = current[stone]
35
+ next[l] = get! (next, l, 0 ) + amount
36
+ r != - 1 && (next[r] = get! (next, r, 0 ) + amount)
44
37
end
45
38
end
46
- return stones[0 ] |> values |> sum
39
+
40
+ return sum (values (stones[1 ]))
41
+ end
47
42
43
+ function continue_stones! (stones, start_runtime, target_runtime, lookup)
44
+ remaining = target_runtime - start_runtime
45
+ stones[remaining+ 1 ] = copy (stones[1 ])
46
+ # Clear intermediate levels
47
+ for i in 1 : remaining
48
+ empty! (stones[i])
49
+ end
50
+
51
+ @inbounds for rt in remaining: - 1 : 1
52
+ current = stones[rt+ 1 ]
53
+ next = stones[rt]
54
+ for stone in keys (current)
55
+ l, r = get_transformation (stone, lookup)
56
+ amount = current[stone]
57
+ next[l] = get! (next, l, 0 ) + amount
58
+ r != - 1 && (next[r] = get! (next, r, 0 ) + amount)
59
+ end
60
+ end
61
+
62
+ return sum (values (stones[1 ]))
48
63
end
49
64
50
- function split_number (number:: Int )
51
- digs = digits (number)
52
- n = length (digs)
53
- l = @view (digs[n÷ 2 + 1 : end ]) .* [10 ^ x for x ∈ 0 : n÷ 2 - 1 ] |> sum
54
- r = @view (digs[1 : n÷ 2 ]) .* [10 ^ x for x ∈ 0 : n÷ 2 - 1 ] |> sum
55
- return l, r
65
+ @inline function get_transformation (stone, lookup)
66
+ return get! (lookup, stone) do
67
+ digs = digits (stone)
68
+ n = length (digs)
69
+ if iseven (n)
70
+ l = sum (@view (digs[n÷ 2 + 1 : end ]) .* [10 ^ x for x ∈ 0 : n÷ 2 - 1 ])
71
+ r = sum (@view (digs[1 : n÷ 2 ]) .* [10 ^ x for x ∈ 0 : n÷ 2 - 1 ])
72
+ (l, r)
73
+ else
74
+ (stone * 2024 , - 1 )
75
+ end
76
+ end
56
77
end
57
78
58
- end # module
79
+ end # module
0 commit comments