From 030fd73babc9eb401a5b444748042ffcff307616 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 24 Dec 2024 20:23:23 +0000 Subject: [PATCH] Add 2024 day 24 part 2 For part 2 we only use helper functions most of the calculations are done manually. --- bin/day2424.ml | 55 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/bin/day2424.ml b/bin/day2424.ml index 064d190..136cd8b 100644 --- a/bin/day2424.ml +++ b/bin/day2424.ml @@ -77,19 +77,58 @@ let process_gates wires = impl wires [] let rec repeat_to_end wires gates = + let old_len = List.length gates in let wires, gates = process_gates wires gates in - if gates = [] then wires + if gates = [] then Some wires + else if old_len = List.length gates then begin + Printf.printf "Loop detected: %d\n" (List.length gates); + None + end else begin - Printf.printf "Gate size: %d\n" (List.length gates); repeat_to_end wires gates end let calc_value = Fun.flip (List.fold_right (fun x acc -> x + (2 * acc))) 0 -let part1 (wires, gates) = - let wires = repeat_to_end wires gates in - let zmap = StringMap.filter (fun k _ -> k.[0] = 'z') wires in - let zlst = StringMap.bindings zmap |> List.map snd in - calc_value zlst +let k_wires wires x = + StringMap.filter (fun k _ -> k.[0] = x) wires + |> StringMap.bindings |> List.map snd |> calc_value -let _ = Aoc.main config_of_file [ (string_of_int, part1) ] +let wires_set wires x v' = + let set_v k v = + if k.[0] = x then + let idx = int_of_string (String.sub k 1 (String.length k - 1)) in + (v' lsr idx) land 1 + else v + in + StringMap.mapi set_v wires + +let part1 (wires, gates) = + match repeat_to_end wires gates with + | None -> failwith "part1" + | Some wires -> k_wires wires 'z' + +let part2 (wires, gates) = + let run_test x y = + let wires = wires_set wires 'x' x in + let wires = wires_set wires 'y' y in + Printf.printf "%d + %d = " (k_wires wires 'x') (k_wires wires 'y'); + match repeat_to_end wires gates with + | None -> print_endline "(infinite loop)" + | Some wires -> + let z = k_wires wires 'z' in + print_int z; + if z <> x + y then print_string " (wrong answer)"; + print_newline () + in + let tst n = + Printf.printf "Test for n = %d\n" n; + run_test (1 lsl n) 0; + run_test 0 (1 lsl n); + run_test (1 lsl n) (1 lsl n) + in + Seq.ints 0 |> Seq.take 45 |> Seq.iter tst; + 0 + +let _ = + Aoc.main config_of_file [ (string_of_int, part1); (string_of_int, part2) ]