put packet in a inline module cuz why not
This commit is contained in:
1 parent
06f695b34c
commit
8fe7e77b52
1 file changed
+48
-51
+48
-51
@@ -1,63 +1,60 @@
|
|||||||
open Containers
|
open Containers
|
||||||
|
|
||||||
type packet =
|
module Packet = struct
|
||||||
| I of int
|
type t =
|
||||||
| L of packet list
|
| I of int
|
||||||
[@@deriving show { with_path = false }]
|
| L of t list
|
||||||
|
[@@deriving show { with_path = false }]
|
||||||
|
|
||||||
let packet_of_str line =
|
let of_str line =
|
||||||
let open Angstrom in
|
let open Angstrom in
|
||||||
let int =
|
let int =
|
||||||
take_while1 (function
|
take_while1 (function
|
||||||
| '0' .. '9' -> true
|
| '0' .. '9' -> true
|
||||||
| _ -> false)
|
| _ -> false)
|
||||||
>>= fun s -> return @@ I (int_of_string s) <?> "int"
|
>>= fun s -> return @@ I (int_of_string s) <?> "int"
|
||||||
in
|
in
|
||||||
let packet =
|
let packet =
|
||||||
fix (fun packet ->
|
fix (fun packet ->
|
||||||
let lb, rb = char '[', char ']' in
|
let lb, delimited, rb = char '[', sep_by (char ','), char ']' in
|
||||||
let delim = sep_by (char ',') in
|
let list = lb *> delimited packet <* rb >>= fun p -> return @@ L p <?> "list" in
|
||||||
let list = lb *> delim packet <* rb >>= fun p -> return @@ L p <?> "list" in
|
choice [ int; list ])
|
||||||
choice [ int; list ])
|
<?> "packet"
|
||||||
<?> "packet"
|
in
|
||||||
in
|
Result.get_or_failwith @@ parse_string ~consume:All packet line
|
||||||
Result.get_or_failwith @@ parse_string ~consume:All packet line
|
;;
|
||||||
;;
|
|
||||||
|
|
||||||
let rec is_ordered a b =
|
let rec compare a b =
|
||||||
match a, b with
|
match a, b with
|
||||||
| I a, I b -> Int.compare a b
|
| I a, I b -> Int.compare a b
|
||||||
| L a, L b -> List.compare is_ordered a b
|
| L a, L b -> List.compare compare a b
|
||||||
| (I _ as a), (L _ as b) -> is_ordered (L [ a ]) b
|
| (I _ as a), (L _ as b) -> compare (L [ a ]) b
|
||||||
| (L _ as a), (I _ as b) -> is_ordered a (L [ b ])
|
| (L _ as a), (I _ as b) -> compare a (L [ b ])
|
||||||
;;
|
;;
|
||||||
|
end
|
||||||
|
|
||||||
let%expect_test "Day 13.1" =
|
let%expect_test "Day 13.1" =
|
||||||
let result =
|
Utils.lines_of_input 13
|
||||||
Utils.lines_of_input 13
|
|> List.filter Fun.(not % String.is_empty)
|
||||||
|> List.filter Fun.(not % String.is_empty)
|
|> List.map Packet.of_str
|
||||||
|> List.map packet_of_str
|
|> List.chunks 2
|
||||||
|> List.chunks 2
|
|> List.mapi (fun i packets ->
|
||||||
|> List.mapi (fun i packets ->
|
match packets with
|
||||||
match packets with
|
| [ a; b ] when Packet.compare a b < 0 -> i + 1
|
||||||
| [ a; b ] when is_ordered a b < 0 -> i + 1
|
| _ -> 0)
|
||||||
| _ -> 0)
|
|> List.reduce_exn ( + )
|
||||||
|> List.reduce_exn ( + )
|
|> print_int;
|
||||||
in
|
|
||||||
Printf.printf "%i" result;
|
|
||||||
[%expect {| 6272 |}]
|
[%expect {| 6272 |}]
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let%expect_test "Day 13.2" =
|
let%expect_test "Day 13.2" =
|
||||||
let result =
|
Utils.lines_of_input 13
|
||||||
Utils.lines_of_input 13
|
|> List.filter Fun.(not % String.is_empty)
|
||||||
|> List.filter Fun.(not % String.is_empty)
|
|> List.map (fun line -> false, Packet.of_str line)
|
||||||
|> List.map (fun line -> false, packet_of_str line)
|
|> List.append [ true, Packet.of_str "[[2]]"; true, Packet.of_str "[[6]]" ]
|
||||||
|> List.append [ true, packet_of_str "[[2]]"; true, packet_of_str "[[6]]" ]
|
|> List.sort (fun (_, a) (_, b) -> Packet.compare a b)
|
||||||
|> List.sort (fun (_, a) (_, b) -> is_ordered a b)
|
|> List.mapi (fun i (is_divider, _) -> if is_divider then i + 1 else 1)
|
||||||
|> List.mapi (fun i (is_divider, _) -> if is_divider then i + 1 else 1)
|
|> List.reduce_exn ( * )
|
||||||
|> List.reduce_exn ( * )
|
|> print_int;
|
||||||
in
|
|
||||||
Printf.printf "%i" result;
|
|
||||||
[%expect {| 22288 |}]
|
[%expect {| 22288 |}]
|
||||||
;;
|
;;
|
||||||
Reference in new issue
Block a user