diff --git a/bin/day2401.ml b/bin/day2401.ml index 754c762..a0ed08f 100644 --- a/bin/day2401.ml +++ b/bin/day2401.ml @@ -1,11 +1,7 @@ -(** [nums_from_string s] takes a string of space separated integers and gives - back a list of the integers. *) -let nums_from_string s = List.map int_of_string (Str.split (Str.regexp " +") s) - (** [pair_nums_from_string s] takes a string of two numbers separated by whitespace and returns the pair of the numbers *) let pair_nums_from_string s = - match nums_from_string s with + match Aoc.nums_from_string s with | [ h; h' ] -> (h, h') | _ -> raise (Invalid_argument "pair_nums_from_string") @@ -19,9 +15,6 @@ let rev_split lst = in impl [] [] lst -(** [distance a b] returns the absolute difference between [a] and [b]. *) -let distance a b = abs (a - b) - (** [count lst n] counts the number of times [n] appears as an element in [lst]. *) let count lst n = @@ -33,12 +26,10 @@ let accumulate = List.fold_left ( + ) 0 (** [lists_from_file fname] Read two lists of integers from [fname] and return as a pair. *) let lists_from_file fname = - In_channel.with_open_text fname In_channel.input_lines - |> List.map pair_nums_from_string - |> rev_split + Aoc.strings_from_file fname |> List.map pair_nums_from_string |> rev_split let day2401a a b = - List.map2 distance (List.sort Int.compare a) (List.sort Int.compare 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 diff --git a/bin/day2402.ml b/bin/day2402.ml new file mode 100644 index 0000000..5e70a74 --- /dev/null +++ b/bin/day2402.ml @@ -0,0 +1,36 @@ +(** [is_monotonic pred lst] returns true if [pred] returns true when tested on + all consecutive elements of [lst]. *) +let rec is_monotonic pred = function + | [] | _ :: [] -> true + | h :: h' :: t -> pred h h' && is_monotonic pred (h' :: t) + +let is_safe lst = + (is_monotonic ( < ) lst || is_monotonic ( > ) lst) + && is_monotonic (fun a b -> Aoc.distance1 a b <= 3) lst + +let is_safe_dampened lst = + let rec impl acc = function + | [] -> is_safe acc + | h :: t -> is_safe (acc @ t) || impl (acc @ [ h ]) t + in + impl [] lst + +let nums_from_file fname = + Aoc.strings_from_file fname |> List.map Aoc.nums_from_string + +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 diff --git a/bin/dune b/bin/dune index f5aa6c5..a3f35b9 100644 --- a/bin/dune +++ b/bin/dune @@ -1,4 +1,4 @@ (executables - (public_names day2401) - (names day2401) - (libraries str)) + (public_names day2401 day2402) + (names day2401 day2402) + (libraries str aoc)) diff --git a/lib/aoc.ml b/lib/aoc.ml new file mode 100644 index 0000000..cb7dff6 --- /dev/null +++ b/lib/aoc.ml @@ -0,0 +1,5 @@ +let nums_from_string s = List.map int_of_string (Str.split (Str.regexp " +") s) +let distance1 a b = abs (a - b) + +let strings_from_file fname = + In_channel.with_open_text fname In_channel.input_lines diff --git a/lib/aoc.mli b/lib/aoc.mli new file mode 100644 index 0000000..b875046 --- /dev/null +++ b/lib/aoc.mli @@ -0,0 +1,10 @@ +val nums_from_string : string -> int list +(** [nums_from_string s] takes a string of space separated integers and gives + back a list of the integers. *) + +val distance1 : int -> int -> int +(** [distance1 a b] returns the absolute difference between [a] and [b]. *) + +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. *) diff --git a/lib/dune b/lib/dune new file mode 100644 index 0000000..9982687 --- /dev/null +++ b/lib/dune @@ -0,0 +1,3 @@ +(library + (name aoc) + (libraries str))