Skip to content

Commit 7b9c3a6

Browse files
committed
[Day 24] Optimize (huge runtime improvement)
Observation: `ruleorder` remains valid for evaluation order, as dependency structure changes are minimal and still acyclic.
1 parent 2ad7db2 commit 7b9c3a6

File tree

2 files changed

+6
-55
lines changed

2 files changed

+6
-55
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ This Julia package contains my solutions for [Advent of Code 2024](https://adven
3333
| 21 | [:white_check_mark:](https://adventofcode.com/2024/day/21) | Path Finding, Simulation | Memoization, Graph Traversal, Deque | 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) | Simulation | Bitwise operations, Hashing, Memoization | 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) | Graph | DFS, Clique Detection, Adjacency Matrix | 4.197 ms | 3.82 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day23.jl) |
36-
| 24 | [:white_check_mark:](https://adventofcode.com/2024/day/24) | Logic | Topological Sorting, Bitwise Operations | 2.497 s | 4.82 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day24.jl) |
36+
| 24 | [:white_check_mark:](https://adventofcode.com/2024/day/24) | Logic | Topological Sorting, Bitwise Operations | 310.021 ms | 2.16 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day24.jl) |
3737
| 25 | [:white_check_mark:](https://adventofcode.com/2024/day/25) | Matching | Brute Force | 2.178 ms | 3.47 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day25.jl) |
3838

3939

src/day24.jl

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function day24(input::String = readInput(joinpath(@__DIR__, "..", "data", "day24
88

99
swapped_outputs = String[]
1010
swapped_inds = Int[]
11-
wrong_adders = [i for i 0:44 if !check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, [i])[1]]
11+
wrong_adders = [i for i 0:44 if !check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, [i], ruleorder)[1]]
1212

1313
suspicious_rules = findall(x -> startswith(rules[x][4], "z") && rules[x][4] != "z45" && rules[x][1] != "XOR", 1:length(rules))
1414

@@ -28,9 +28,9 @@ function day24(input::String = readInput(joinpath(@__DIR__, "..", "data", "day24
2828
for rj nrules
2929
ri == rj && continue
3030
first, second = swap_outputs!(rules, ri, rj)
31-
corrects_critical, _ = check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, sequence)
31+
corrects_critical, _ = check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, sequence, ruleorder)
3232
if corrects_critical
33-
success, _ = check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, setdiff(0:44, wrong_adders))
33+
success, _ = check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, setdiff(0:44, wrong_adders), ruleorder)
3434
if success
3535
push!(swapped_outputs, (first, second)...)
3636
push!(swapped_inds, (ri, rj)...)
@@ -207,7 +207,7 @@ function needed_rules_optimized(rules::Vector{NTuple{4, String}}, outinds::Vecto
207207
return needed
208208
end
209209

210-
function check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, indices)
210+
function check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, indices, ruleorder)
211211
xi = (1, 1, 0, 1, 1)
212212
yi = (0, 1, 0, 0, 1)
213213
cprev = (0, 0, 1, 1, 1)
@@ -216,7 +216,7 @@ function check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, indices
216216
for i iter
217217
x_val = (xi[i] << index) + (cprev[i] << (index - 1))
218218
y_val = (yi[i] << index) + (cprev[i] << (index - 1))
219-
result = run_dynamic(x_val, y_val, rules, var_ids, x_bits, y_bits, z_outputs)
219+
result = run_optimized(x_val, y_val, rules, var_ids, x_bits, y_bits, z_outputs, ruleorder)
220220
expected = x_val + y_val
221221
if result != expected
222222
return false, nothing
@@ -226,53 +226,4 @@ function check_adders_dynamic(rules, var_ids, x_bits, y_bits, z_outputs, indices
226226
return true, nothing
227227
end
228228

229-
function run_dynamic(x::Int, y::Int, rules::Vector{NTuple{4, String}}, var_ids::Dict{String, Int}, x_bits::Dict{Int, Int}, y_bits::Dict{Int, Int}, z_outputs::Vector{String})
230-
max_id = maximum(values(var_ids))
231-
state = falses(max_id)
232-
computed = falses(max_id)
233-
234-
for (id, idx) x_bits
235-
state[id] = (x >> idx) & 1 == 1
236-
computed[id] = true
237-
end
238-
for (id, idx) y_bits
239-
state[id] = (y >> idx) & 1 == 1
240-
computed[id] = true
241-
end
242-
243-
processed = falses(length(rules))
244-
any_changes = true
245-
while any_changes
246-
any_changes = false
247-
for (ri, rule) enumerate(rules)
248-
processed[ri] && continue
249-
op, left, right, output = rule
250-
lid = var_ids[left]
251-
rid = var_ids[right]
252-
oid = var_ids[output]
253-
if computed[lid] && computed[rid]
254-
lval = state[lid]
255-
rval = state[rid]
256-
if op == "AND"
257-
state[oid] = lval & rval
258-
elseif op == "OR"
259-
state[oid] = lval | rval
260-
elseif op == "XOR"
261-
state[oid] = lval rval
262-
end
263-
computed[oid] = true
264-
processed[ri] = true
265-
any_changes = true
266-
end
267-
end
268-
end
269-
270-
result = 0
271-
for (i, z) enumerate(z_outputs)
272-
oid = var_ids[z]
273-
computed[oid] && (result += state[oid] << (i - 1))
274-
end
275-
return result
276-
end
277-
278229
end # module

0 commit comments

Comments
 (0)