@@ -247,4 +247,201 @@ function check_adders_at_indices(rules::Vector{NTuple{4, String}}, indices::Vect
247
247
return true , ruleorder
248
248
end
249
249
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