aoc2020/misc.ml

70 lines
1.7 KiB
OCaml

let usage args =
let err = Format.sprintf "usage: %s %s" Sys.argv.(0) args in
print_endline err;
exit 1
let usage_default day = usage (string_of_int day ^ " <part> <infile>")
let main day mains = function
| [part; input] -> mains.(int_of_string part - 1) input
| _ -> usage_default day
type 'a monoid =
{id: 'a;
op: 'a -> 'a -> 'a;
op_name: string;
pp: Format.formatter -> 'a -> unit}
let mult = {id = 1; op = ( * ); op_name = "*"; pp = Format.pp_print_int}
let add = {id = 0; op = ( + ); op_name = "+"; pp = Format.pp_print_int}
let fold_list {op; id; _} = List.fold_left op id
let%test _ = fold_list add [] = 0
let%test _ = fold_list add [1;2;3;4] = 10
let%test _ = fold_list mult [1;2;3;4] = 24
let print_fold ?(format=false) mon xs =
let res = List.fold_left mon.op mon.id xs in
let rec go fmt = function
| [] -> Format.fprintf fmt "%a" mon.pp mon.id
| [x] -> Format.fprintf fmt "%a" mon.pp x
| x::xs ->
let f =
if format then Format.fprintf fmt "%a %s@ %a"
else Format.fprintf fmt "%a %s %a" in
f mon.pp x mon.op_name go xs in
let f =
if format then Format.printf "%a =@ %a\n"
else Format.printf "%a = %a\n" in
f go xs mon.pp res
let print_prod ?format = print_fold ?format mult
let print_sum ?format = print_fold ?format add
let%expect_test _ =
print_prod [];
[%expect{| 1 = 1 |}]
let%expect_test _ =
print_prod [1];
[%expect{| 1 = 1 |}]
let%expect_test _ =
print_prod [1;2;3;4];
[%expect{| 1 * 2 * 3 * 4 = 24 |}]
let%expect_test _ =
print_sum [];
[%expect{| 0 = 0 |}]
let%expect_test _ =
print_sum [1];
[%expect{| 1 = 1 |}]
let%expect_test _ =
print_sum [1;2;3;4];
[%expect{| 1 + 2 + 3 + 4 = 10 |}]