Skip to content

Commit eed9094

Browse files
committed
[Day 11] Slight improvement
1 parent 3b5b552 commit eed9094

File tree

3 files changed

+202
-5
lines changed

3 files changed

+202
-5
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This Julia package contains my solutions for [Advent of Code 2024](https://adven
2020
| 8 | [:white_check_mark:](https://adventofcode.com/2024/day/8) | 316.122 μs | 671.41 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day08.jl) |
2121
| 9 | [:white_check_mark:](https://adventofcode.com/2024/day/9) | 28.732 ms | 9.58 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day09.jl) |
2222
| 10 | [:white_check_mark:](https://adventofcode.com/2024/day/10) | 578.868 μs | 633.67 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day10.jl) |
23-
| 11 | [:white_check_mark:](https://adventofcode.com/2024/day/11) | 15.732 ms | 12.60 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day11.jl) |
23+
| 11 | [:white_check_mark:](https://adventofcode.com/2024/day/11) | 15.667 ms | 12.60 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day11.jl) |
2424
| 12 | [:white_check_mark:](https://adventofcode.com/2024/day/12) | 12.204 ms | 10.00 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day12.jl) |
2525
| 13 | [:white_check_mark:](https://adventofcode.com/2024/day/13) | 3.101 ms | 1.15 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day13.jl) |
2626
| 14 | [:white_check_mark:](https://adventofcode.com/2024/day/14) | 75.842 ms | 275.06 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day14.jl) |
@@ -96,4 +96,4 @@ julia> AdventOfCode2024.Day01.day01(input)
9696
2-element Vector{Int64}:
9797
1590491
9898
22588371
99-
```
99+
```

src/day11.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function solve(data, runtime)
1717
for value data
1818
stones[runtime][value] = 1
1919
end
20-
for rt runtime:-1:1
20+
@inbounds for rt runtime:-1:1
2121
for stone keys(stones[rt])
2222
if haskey(lookup, stone)
2323
l, r = lookup[stone]
@@ -55,4 +55,4 @@ function split_number(number::Int)
5555
return l, r
5656
end
5757

58-
end # module
58+
end # module

src/day24.jl

Lines changed: 198 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,201 @@ function check_adders_at_indices(rules::Vector{NTuple{4, String}}, indices::Vect
247247
return true, ruleorder
248248
end
249249

250-
end # module
250+
end # module
251+
252+
253+
# module Day24
254+
255+
# using AdventOfCode2024
256+
257+
# struct Gate
258+
# op::Symbol # :AND, :OR, :XOR
259+
# in1::Int # Input index
260+
# in2::Int # Input index
261+
# out::Int # Output index
262+
# end
263+
264+
# function parse_input(input::String)
265+
# sections = split(input, "\n\n")
266+
# init_section, rules_section = sections[1], sections[2]
267+
268+
# # Parse initial x/y values using bitwise operations
269+
# x = y = 0
270+
# for line in split(init_section, '\n')
271+
# parts = split(line, r"[: ]+", keepempty=false)
272+
# bit = parse(Int, parts[3])
273+
# idx = parse(Int, parts[1][2:end])
274+
# if parts[1][1] == 'x'
275+
# x |= bit << idx
276+
# else
277+
# y |= bit << idx
278+
# end
279+
# end
280+
281+
# # Create node index mapping
282+
# node_map = Dict{String,Int}()
283+
# node_count = 0
284+
285+
# function get_index!(id::String)
286+
# if !haskey(node_map, id)
287+
# node_count += 1
288+
# node_map[id] = node_count
289+
# end
290+
# node_map[id]
291+
# end
292+
293+
# # Pre-map x/y inputs (0-44 for x00-x44 and y00-y44)
294+
# for i in 0:44
295+
# get_index!("x$(lpad(i, 2, '0'))")
296+
# get_index!("y$(lpad(i, 2, '0'))")
297+
# end
298+
299+
# # Parse gates and build dependency graph
300+
# gates = Gate[]
301+
# in_degree = Dict{Int,Int}()
302+
# adjacency = Dict{Int,Vector{Int}}()
303+
304+
# for line in split(rules_section, '\n')
305+
# parts = split(line, " -> ")
306+
# op_inputs = split(parts[1])
307+
# out = get_index!(parts[2])
308+
309+
# op = Symbol(op_inputs[1])
310+
# in1 = get_index!(op_inputs[2])
311+
# in2 = get_index!(op_inputs[3])
312+
313+
# push!(gates, Gate(op, in1, in2, out))
314+
315+
# # Build dependency graph for topological sort
316+
# for input in [in1, in2]
317+
# push!(get!(adjacency, input, Int[]), out)
318+
# in_degree[out] = get(in_degree, out, 0) + 1
319+
# end
320+
# end
321+
322+
# # Topological sort using Kahn's algorithm
323+
# queue = [i for i in 1:node_count if get(in_degree, i, 0) == 0]
324+
# order = Int[]
325+
326+
# while !isempty(queue)
327+
# node = popfirst!(queue)
328+
# push!(order, node)
329+
# for neighbor in get(adjacency, node, [])
330+
# in_degree[neighbor] -= 1
331+
# in_degree[neighbor] == 0 && push!(queue, neighbor)
332+
# end
333+
# end
334+
335+
# # Filter and order gates based on topological sort
336+
# ordered_gates = [gate for gate in gates if gate.out in order]
337+
338+
# return x, y, ordered_gates, node_map
339+
# end
340+
341+
# function compute_output(x::Int, y::Int, gates::Vector{Gate}, node_map::Dict{String,Int})
342+
# max_node = maximum(values(node_map))
343+
# state = zeros(Bool, max_node)
344+
345+
# # Initialize x/y inputs
346+
# for i in 0:44
347+
# state[node_map["x$(lpad(i, 2, '0'))"]] = (x >> i) & 1
348+
# state[node_map["y$(lpad(i, 2, '0'))"]] = (y >> i) & 1
349+
# end
350+
351+
# # Process gates in topological order
352+
# for gate in gates
353+
# a = state[gate.in1]
354+
# b = state[gate.in2]
355+
# state[gate.out] = if gate.op == :AND
356+
# a & b
357+
# elseif gate.op == :OR
358+
# a | b
359+
# else # XOR
360+
# a ⊻ b
361+
# end
362+
# end
363+
364+
# # Collect z outputs
365+
# result = 0
366+
# for i in 0:44
367+
# z_idx = node_map["z$(lpad(i, 2, '0'))"]
368+
# result |= state[z_idx] << i
369+
# end
370+
# result
371+
# end
372+
373+
# function find_sequences(arr::Vector{Int})
374+
# isempty(arr) && return Vector{Int}[]
375+
# sort!(arr)
376+
# sequences = Vector{Int}[]
377+
# current = [arr[1]]
378+
379+
# for val in arr[2:end]
380+
# val == current[end] + 1 ? push!(current, val) : begin
381+
# push!(sequences, current)
382+
# current = [val]
383+
# end
384+
# end
385+
# push!(sequences, current)
386+
# return sequences
387+
# end
388+
389+
# function check_adders(x::Int, y::Int, gates::Vector{Gate}, node_map::Dict{String,Int}, indices::Vector{Int})
390+
# expected = x + y
391+
# result = compute_output(x, y, gates, node_map)
392+
# (result & ((1 << (maximum(indices)+1)) - 1)) == (expected & ((1 << (maximum(indices)+1)) - 1))
393+
# end
394+
395+
# function needed_gates(gates::Vector{Gate}, node_map::Dict{String,Int}, out_indices::Vector{Int})
396+
# z_ids = [node_map["z$(lpad(i, 2, '0'))"] for i in out_indices]
397+
# required = Set{Int}(z_ids)
398+
# queue = copy(z_ids)
399+
400+
# while !isempty(queue)
401+
# out = pop!(queue)
402+
# for gate in gates
403+
# if gate.out == out
404+
# push!(required, gate.in1, gate.in2)
405+
# push!(queue, gate.in1, gate.in2)
406+
# end
407+
# end
408+
# end
409+
# return required
410+
# end
411+
412+
# function swap_gates!(gates::Vector{Gate}, i::Int, j::Int)
413+
# gates[i], gates[j] = gates[j], gates[i]
414+
# end
415+
416+
# function day24(input::String = readInput(joinpath(@__DIR__, "..", "data", "day24.txt")))
417+
# x, y, gates, node_map = parse_input(input)
418+
# p1 = compute_output(x, y, gates, node_map)
419+
420+
# # Part 2: Find and fix swapped gates
421+
# test_cases = [(0b1100, 0b0110), (0b1010, 0b0101), (0b1111, 0b0000)] # Example test cases
422+
# suspicious = findall(g -> g.op != :XOR && node_map["z45"] ∉ [g.in1, g.in2], gates)
423+
# swapped = String[]
424+
425+
# for seq in find_sequences([i for i in 0:44 if !check_adders(0, 0, gates, node_map, [i])])
426+
# needed = needed_gates(gates, node_map, seq)
427+
# candidates = intersect(suspicious, needed)
428+
429+
# for (i, j) in Iterators.product(candidates, candidates)
430+
# i == j && continue
431+
# swap_gates!(gates, i, j)
432+
433+
# valid = all(tc -> check_adders(tc[1], tc[2], gates, node_map, seq), test_cases)
434+
# if valid
435+
# push!(swapped, "z$(lpad(gates[i].out, 2, '0'))")
436+
# push!(swapped, "z$(lpad(gates[j].out, 2, '0'))")
437+
# break
438+
# else
439+
# swap_gates!(gates, i, j) # Revert if not valid
440+
# end
441+
# end
442+
# end
443+
444+
# return [p1, join(sort!(swapped), ",")]
445+
# end
446+
447+
# end # module

0 commit comments

Comments
 (0)