diff --git a/bin/day2401.ml b/bin/day2401.ml index a0ed08f..0d51610 100644 --- a/bin/day2401.ml +++ b/bin/day2401.ml @@ -28,22 +28,12 @@ let accumulate = List.fold_left ( + ) 0 let lists_from_file fname = Aoc.strings_from_file fname |> List.map pair_nums_from_string |> rev_split -let day2401a a b = +let day2401a (a, b) = List.map2 Aoc.distance1 (List.sort Int.compare a) (List.sort Int.compare b) |> accumulate -let day2401b a b = List.map (count b) a |> List.map2 ( * ) a |> accumulate +let day2401b (a, b) = List.map (count b) a |> List.map2 ( * ) a |> accumulate let _ = - try - match Sys.argv with - | [| _; fname |] -> - let a, b = lists_from_file fname in - Printf.printf "Part 1 = %d\n" (day2401a a b); - Printf.printf "Part 2 = %d\n" (day2401b a b) - | _ -> - Printf.printf "Usage: day2401 \n"; - exit 1 - with e -> - Printf.printf "An error occured: %s\n" (Printexc.to_string e); - exit 1 + Aoc.main lists_from_file + [ (string_of_int, day2401a); (string_of_int, day2401b) ] diff --git a/bin/day2402.ml b/bin/day2402.ml index 5e70a74..d4e76cd 100644 --- a/bin/day2402.ml +++ b/bin/day2402.ml @@ -22,15 +22,5 @@ let day2402a lsts = List.filter is_safe lsts |> List.length let day2402b lsts = List.filter is_safe_dampened lsts |> List.length let _ = - try - match Sys.argv with - | [| _; fname |] -> - let lines = nums_from_file fname in - Printf.printf "Part 1 = %d\n" (day2402a lines); - Printf.printf "Part 2 = %d\n" (day2402b lines) - | _ -> - Printf.printf "Usage: day2402 \n"; - exit 1 - with e -> - Printf.printf "An error occured: %s\n" (Printexc.to_string e); - exit 1 + Aoc.main nums_from_file + [ (string_of_int, day2402a); (string_of_int, day2402b) ] diff --git a/lib/aoc.ml b/lib/aoc.ml index cb7dff6..05a23c4 100644 --- a/lib/aoc.ml +++ b/lib/aoc.ml @@ -3,3 +3,20 @@ let distance1 a b = abs (a - b) let strings_from_file fname = In_channel.with_open_text fname In_channel.input_lines + +let main prep parts = + try + match Sys.argv with + | [| _; fname |] -> + let lines = prep fname in + let do_part i (fmt, fn) = + Printf.printf "Part %d = %s\n" i (fmt (fn lines)) + in + List.iteri do_part parts; + exit 0 + | _ -> + Printf.printf "Usage: %s \n" Sys.executable_name; + exit 2 + with e -> + Printf.printf "An error occured: %s\n" (Printexc.to_string e); + exit 1 diff --git a/lib/aoc.mli b/lib/aoc.mli index b875046..d5b6fc4 100644 --- a/lib/aoc.mli +++ b/lib/aoc.mli @@ -8,3 +8,11 @@ val distance1 : int -> int -> int val strings_from_file : string -> string list (** [strings_from_file fname] returns a list of strings from the file [fname]. Each string represents a line from the file. *) + +val main : (string -> 'a) -> (('b -> string) * ('a -> 'b)) list -> unit +(** [main prep parts] executes an advent of code problem. [prep fname] should + be a function that returns the input from [fname]. Each elemet of + [parts] is a pair of functions. The first converts the output to a string + (for example [string_of_int]). The second executes the given part. + Output is given as if done by: + [print_string ( prep fname |> snd |> fst )] *)