2024 day 24 part 1
This commit is contained in:
95
bin/day2424.ml
Normal file
95
bin/day2424.ml
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
type op = And | Or | Xor
|
||||||
|
type gate = { in1 : string; in2 : string; op : op; out : string }
|
||||||
|
|
||||||
|
module StringMap = Map.Make (String)
|
||||||
|
|
||||||
|
let get_wire_value str =
|
||||||
|
let re = Str.regexp {|\(.+\): \([01]\)|} in
|
||||||
|
let _ = Str.search_forward re str 0 in
|
||||||
|
let v = if Str.matched_group 2 str = "0" then 0 else 1 in
|
||||||
|
(Str.matched_group 1 str, v)
|
||||||
|
|
||||||
|
let get_gate_op = function
|
||||||
|
| "AND" -> And
|
||||||
|
| "OR" -> Or
|
||||||
|
| "XOR" -> Xor
|
||||||
|
| _ -> failwith "get_gate_op"
|
||||||
|
|
||||||
|
let[@warning "-32"] string_of_op = function
|
||||||
|
| And -> "AND"
|
||||||
|
| Or -> "OR"
|
||||||
|
| Xor -> "XOR"
|
||||||
|
|
||||||
|
let get_gate_config str =
|
||||||
|
let re = Str.regexp {|\(.+\) \(AND\|OR\|XOR\) \(.+\) -> \(.+\)|} in
|
||||||
|
let _ = Str.search_forward re str 0 in
|
||||||
|
let in1 = Str.matched_group 1 str in
|
||||||
|
let op = get_gate_op (Str.matched_group 2 str) in
|
||||||
|
let in2 = Str.matched_group 3 str in
|
||||||
|
let out = Str.matched_group 4 str in
|
||||||
|
{ in1; in2; op; out }
|
||||||
|
|
||||||
|
let initial_wires_of_strings =
|
||||||
|
let rec impl acc = function
|
||||||
|
| "" :: t -> (acc, t)
|
||||||
|
| h :: t ->
|
||||||
|
let wire, v = get_wire_value h in
|
||||||
|
impl (StringMap.add wire v acc) t
|
||||||
|
| _ -> failwith "initial_wires_of_strings"
|
||||||
|
in
|
||||||
|
impl StringMap.empty
|
||||||
|
|
||||||
|
let gates_from_strings =
|
||||||
|
let rec impl acc = function
|
||||||
|
| [] -> acc
|
||||||
|
| h :: t -> impl (get_gate_config h :: acc) t
|
||||||
|
in
|
||||||
|
impl []
|
||||||
|
|
||||||
|
let config_of_file fname =
|
||||||
|
let lst = Aoc.strings_of_file fname in
|
||||||
|
let wires, lst = initial_wires_of_strings lst in
|
||||||
|
let gates = gates_from_strings lst in
|
||||||
|
(wires, gates)
|
||||||
|
|
||||||
|
let process_gate wires gate =
|
||||||
|
match
|
||||||
|
( gate.op,
|
||||||
|
StringMap.find_opt gate.in1 wires,
|
||||||
|
StringMap.find_opt gate.in2 wires )
|
||||||
|
with
|
||||||
|
| And, Some a, Some b -> if a = 1 && b = 1 then Some 1 else Some 0
|
||||||
|
| Or, Some a, Some b -> if a = 1 || b = 1 then Some 1 else Some 0
|
||||||
|
| Xor, Some a, Some b -> if a <> b then Some 1 else Some 0
|
||||||
|
| _, _, _ -> None
|
||||||
|
|
||||||
|
let process_gates wires =
|
||||||
|
let rec impl wires acc = function
|
||||||
|
| [] -> (wires, acc)
|
||||||
|
| h :: t -> begin
|
||||||
|
match process_gate wires h with
|
||||||
|
| None -> impl wires (h :: acc) t
|
||||||
|
| Some x ->
|
||||||
|
let wires = StringMap.add h.out x wires in
|
||||||
|
impl wires acc t
|
||||||
|
end
|
||||||
|
in
|
||||||
|
impl wires []
|
||||||
|
|
||||||
|
let rec repeat_to_end wires gates =
|
||||||
|
let wires, gates = process_gates wires gates in
|
||||||
|
if gates = [] then wires
|
||||||
|
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 _ = Aoc.main config_of_file [ (string_of_int, part1) ]
|
Reference in New Issue
Block a user