diff --git a/src/day13.ml b/src/day13.ml index ad9c1ad..ddd52c0 100644 --- a/src/day13.ml +++ b/src/day13.ml @@ -1,63 +1,60 @@ open Containers -type packet = - | I of int - | L of packet list -[@@deriving show { with_path = false }] +module Packet = struct + type t = + | I of int + | L of t list + [@@deriving show { with_path = false }] -let packet_of_str line = - let open Angstrom in - let int = - take_while1 (function - | '0' .. '9' -> true - | _ -> false) - >>= fun s -> return @@ I (int_of_string s) "int" - in - let packet = - fix (fun packet -> - let lb, rb = char '[', char ']' in - let delim = sep_by (char ',') in - let list = lb *> delim packet <* rb >>= fun p -> return @@ L p "list" in - choice [ int; list ]) - "packet" - in - Result.get_or_failwith @@ parse_string ~consume:All packet line -;; + let of_str line = + let open Angstrom in + let int = + take_while1 (function + | '0' .. '9' -> true + | _ -> false) + >>= fun s -> return @@ I (int_of_string s) "int" + in + let packet = + fix (fun packet -> + let lb, delimited, rb = char '[', sep_by (char ','), char ']' in + let list = lb *> delimited packet <* rb >>= fun p -> return @@ L p "list" in + choice [ int; list ]) + "packet" + in + Result.get_or_failwith @@ parse_string ~consume:All packet line + ;; -let rec is_ordered a b = - match a, b with - | I a, I b -> Int.compare a b - | L a, L b -> List.compare is_ordered a b - | (I _ as a), (L _ as b) -> is_ordered (L [ a ]) b - | (L _ as a), (I _ as b) -> is_ordered a (L [ b ]) -;; + let rec compare a b = + match a, b with + | I a, I b -> Int.compare a b + | L a, L b -> List.compare compare a b + | (I _ as a), (L _ as b) -> compare (L [ a ]) b + | (L _ as a), (I _ as b) -> compare a (L [ b ]) + ;; +end let%expect_test "Day 13.1" = - let result = - Utils.lines_of_input 13 - |> List.filter Fun.(not % String.is_empty) - |> List.map packet_of_str - |> List.chunks 2 - |> List.mapi (fun i packets -> - match packets with - | [ a; b ] when is_ordered a b < 0 -> i + 1 - | _ -> 0) - |> List.reduce_exn ( + ) - in - Printf.printf "%i" result; + Utils.lines_of_input 13 + |> List.filter Fun.(not % String.is_empty) + |> List.map Packet.of_str + |> List.chunks 2 + |> List.mapi (fun i packets -> + match packets with + | [ a; b ] when Packet.compare a b < 0 -> i + 1 + | _ -> 0) + |> List.reduce_exn ( + ) + |> print_int; [%expect {| 6272 |}] ;; let%expect_test "Day 13.2" = - let result = - Utils.lines_of_input 13 - |> List.filter Fun.(not % String.is_empty) - |> List.map (fun line -> false, packet_of_str line) - |> List.append [ true, packet_of_str "[[2]]"; true, packet_of_str "[[6]]" ] - |> List.sort (fun (_, a) (_, b) -> is_ordered a b) - |> List.mapi (fun i (is_divider, _) -> if is_divider then i + 1 else 1) - |> List.reduce_exn ( * ) - in - Printf.printf "%i" result; + Utils.lines_of_input 13 + |> List.filter Fun.(not % String.is_empty) + |> List.map (fun line -> false, Packet.of_str line) + |> List.append [ true, Packet.of_str "[[2]]"; true, Packet.of_str "[[6]]" ] + |> List.sort (fun (_, a) (_, b) -> Packet.compare a b) + |> List.mapi (fun i (is_divider, _) -> if is_divider then i + 1 else 1) + |> List.reduce_exn ( * ) + |> print_int; [%expect {| 22288 |}] ;;