diff options
| -rw-r--r-- | 2025/ocaml/lib/application/d03p02.ml | 23 | ||||
| -rw-r--r-- | 2025/ocaml/lib/application/d03p02.mli | 4 | ||||
| -rw-r--r-- | 2025/ocaml/lib/domain/d03p02.ml | 114 | ||||
| -rw-r--r-- | 2025/ocaml/lib/presentation/cli.ml | 1 |
4 files changed, 142 insertions, 0 deletions
diff --git a/2025/ocaml/lib/application/d03p02.ml b/2025/ocaml/lib/application/d03p02.ml new file mode 100644 index 0000000..743c658 --- /dev/null +++ b/2025/ocaml/lib/application/d03p02.ml @@ -0,0 +1,23 @@ +open Domain.D03p02 + +let err_empty_input = "input is empty" + +let to_lines s = + s |> String.split_on_char '\n' |> List.map String.trim + |> List.filter (fun l -> l <> "") + +let solve input () = + if input = "" then Error err_empty_input + else + let answer = + input |> to_lines |> List.to_seq + |> Seq.map BatteryBank.of_string + |> Seq.mapi (fun idx bb -> + let joltage = BatteryBank.highest_joltage bb in + Logs.debug (fun m -> + m "%d line=%s highest_joltage=%d" (idx + 1) (BatteryBank.pp bb) + joltage ) ; + joltage ) + |> Seq.fold_left ( + ) 0 + in + Ok answer diff --git a/2025/ocaml/lib/application/d03p02.mli b/2025/ocaml/lib/application/d03p02.mli new file mode 100644 index 0000000..93d3b98 --- /dev/null +++ b/2025/ocaml/lib/application/d03p02.mli @@ -0,0 +1,4 @@ +val solve : string -> unit -> (int, string) result +(** [solve input ()] is the solution for the second part of the third day of advent of code 2025 for [input]. + The solution for an empty input is [Error msg]. + Requires: [input] to be a string. *) diff --git a/2025/ocaml/lib/domain/d03p02.ml b/2025/ocaml/lib/domain/d03p02.ml new file mode 100644 index 0000000..1367712 --- /dev/null +++ b/2025/ocaml/lib/domain/d03p02.ml @@ -0,0 +1,114 @@ +module Battery : sig + type t + + val of_int : int -> t + + val to_int : t -> int + + val to_string : t -> string + + val compare : t -> t -> int + + val pp : t -> string +end = struct + type t = int + + let of_int i = i + + let to_int b = b + + let to_string = string_of_int + + let compare = Int.compare + + let pp = string_of_int +end + +module BatteryBank : sig + type t + + val highest_joltage : t -> int + (** [highest_joltage bb] is an integer created from the two highest + digits in [bb]. + Raises: [Assert_failure] if [bb] is empty. *) + + val of_string : string -> t + + val of_list : Battery.t list -> t + + val to_list : t -> Battery.t list + + val pp : t -> string +end = struct + type t = Battery.t list + + let rec highest_joltage bb = + assert (List.length bb > 0) ; + match highest_joltage_aux (None, None) bb with + | None, None -> + 0 + | Some x, Some y -> + int_of_string (Battery.to_string x ^ Battery.to_string y) + | _ -> + failwith "highest_joltage must be two digits" + + and highest_joltage_aux acc = function + | [] -> + acc + | [elt] -> ( + match acc with + | None, None -> + (Some (Battery.of_int 0), Some elt) + | Some first, None -> + (Some first, Some elt) + | None, Some second -> + (Some second, Some elt) + | Some first, Some second -> + if elt > second then (Some first, Some elt) + else (Some first, Some second) ) + | h :: t -> + highest_joltage_aux + ( match acc with + | None, None -> + (Some h, None) + | Some first, None -> + let second = Battery.of_int 0 in + swap_if_higher first second h + | Some first, Some second -> + swap_if_higher first second h + | _ -> + failwith "this branch should be impossible" ) + t + + and swap_if_higher first second considering = + assert (first >= second) ; + let c_gt_f = Battery.compare considering first = 1 in + let c_gt_s = Battery.compare considering second = 1 in + match (c_gt_f, c_gt_s) with + | true, true -> + (Some considering, None) + | false, true -> + (Some first, Some considering) + | true, false -> + failwith "[second] should never be greater than [first]" + | false, false -> + (Some first, Some second) + + let of_string s = + s |> String.to_seq + |> Seq.map (fun c -> Char.escaped c |> int_of_string |> Battery.of_int) + |> List.of_seq + + let of_list lst = lst + + let to_list bb = bb + + let pp bb = + "[ " + ^ ( bb |> List.map Battery.pp + |> List.fold_left + (fun acc b -> + if acc = "" then b ^ ";" else Printf.sprintf "%s %s;" acc b ) + "" ) + ^ " ]" +end diff --git a/2025/ocaml/lib/presentation/cli.ml b/2025/ocaml/lib/presentation/cli.ml index f4c57e6..7864e7f 100644 --- a/2025/ocaml/lib/presentation/cli.ml +++ b/2025/ocaml/lib/presentation/cli.ml @@ -22,6 +22,7 @@ let run_day _ = function | 3 -> let filepath = "../_input/day_03.txt" in run_solver "D03P01" Application.D03p01.solve filepath ; + run_solver "D03P02" Application.D03p02.solve filepath ; 0 | 4 -> let filepath = "../_input/day_04.txt" in |
