From 976048a85403fbb0751c34fa42703a3c47f6e918 Mon Sep 17 00:00:00 2001 From: DJ O'Leary Date: Sat, 27 Jun 2026 00:11:43 +0200 Subject: refactor!: change repo directory structure for ocaml --- ocaml/lib/year2025/day03/part01/battery.ml | 13 ++++ ocaml/lib/year2025/day03/part01/battery.mli | 13 ++++ ocaml/lib/year2025/day03/part01/battery_bank.ml | 75 +++++++++++++++++++++++ ocaml/lib/year2025/day03/part01/battery_bank.mli | 18 ++++++ ocaml/lib/year2025/day03/part01/solver.ml | 23 +++++++ ocaml/lib/year2025/day03/part01/solver.mli | 4 ++ ocaml/lib/year2025/day03/part02/battery.ml | 25 ++++++++ ocaml/lib/year2025/day03/part02/battery.mli | 13 ++++ ocaml/lib/year2025/day03/part02/battery_bank.ml | 77 ++++++++++++++++++++++++ ocaml/lib/year2025/day03/part02/battery_bank.mli | 18 ++++++ ocaml/lib/year2025/day03/part02/solver.ml | 23 +++++++ ocaml/lib/year2025/day03/part02/solver.mli | 4 ++ 12 files changed, 306 insertions(+) create mode 100644 ocaml/lib/year2025/day03/part01/battery.ml create mode 100644 ocaml/lib/year2025/day03/part01/battery.mli create mode 100644 ocaml/lib/year2025/day03/part01/battery_bank.ml create mode 100644 ocaml/lib/year2025/day03/part01/battery_bank.mli create mode 100644 ocaml/lib/year2025/day03/part01/solver.ml create mode 100644 ocaml/lib/year2025/day03/part01/solver.mli create mode 100644 ocaml/lib/year2025/day03/part02/battery.ml create mode 100644 ocaml/lib/year2025/day03/part02/battery.mli create mode 100644 ocaml/lib/year2025/day03/part02/battery_bank.ml create mode 100644 ocaml/lib/year2025/day03/part02/battery_bank.mli create mode 100644 ocaml/lib/year2025/day03/part02/solver.ml create mode 100644 ocaml/lib/year2025/day03/part02/solver.mli (limited to 'ocaml/lib/year2025/day03') diff --git a/ocaml/lib/year2025/day03/part01/battery.ml b/ocaml/lib/year2025/day03/part01/battery.ml new file mode 100644 index 0000000..cb2d9e5 --- /dev/null +++ b/ocaml/lib/year2025/day03/part01/battery.ml @@ -0,0 +1,13 @@ +module Battery = 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 diff --git a/ocaml/lib/year2025/day03/part01/battery.mli b/ocaml/lib/year2025/day03/part01/battery.mli new file mode 100644 index 0000000..e00940b --- /dev/null +++ b/ocaml/lib/year2025/day03/part01/battery.mli @@ -0,0 +1,13 @@ +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 diff --git a/ocaml/lib/year2025/day03/part01/battery_bank.ml b/ocaml/lib/year2025/day03/part01/battery_bank.ml new file mode 100644 index 0000000..7ebce75 --- /dev/null +++ b/ocaml/lib/year2025/day03/part01/battery_bank.ml @@ -0,0 +1,75 @@ +open Battery + +module BatteryBank = 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/ocaml/lib/year2025/day03/part01/battery_bank.mli b/ocaml/lib/year2025/day03/part01/battery_bank.mli new file mode 100644 index 0000000..bffc4cb --- /dev/null +++ b/ocaml/lib/year2025/day03/part01/battery_bank.mli @@ -0,0 +1,18 @@ +open Battery + +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 diff --git a/ocaml/lib/year2025/day03/part01/solver.ml b/ocaml/lib/year2025/day03/part01/solver.ml new file mode 100644 index 0000000..4a06e83 --- /dev/null +++ b/ocaml/lib/year2025/day03/part01/solver.ml @@ -0,0 +1,23 @@ +open Battery_bank + +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/ocaml/lib/year2025/day03/part01/solver.mli b/ocaml/lib/year2025/day03/part01/solver.mli new file mode 100644 index 0000000..31dd0cd --- /dev/null +++ b/ocaml/lib/year2025/day03/part01/solver.mli @@ -0,0 +1,4 @@ +val solve : string -> unit -> (int, string) result +(** [solve input ()] is the solution for the first 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/ocaml/lib/year2025/day03/part02/battery.ml b/ocaml/lib/year2025/day03/part02/battery.ml new file mode 100644 index 0000000..e8f0443 --- /dev/null +++ b/ocaml/lib/year2025/day03/part02/battery.ml @@ -0,0 +1,25 @@ +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 diff --git a/ocaml/lib/year2025/day03/part02/battery.mli b/ocaml/lib/year2025/day03/part02/battery.mli new file mode 100644 index 0000000..e00940b --- /dev/null +++ b/ocaml/lib/year2025/day03/part02/battery.mli @@ -0,0 +1,13 @@ +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 diff --git a/ocaml/lib/year2025/day03/part02/battery_bank.ml b/ocaml/lib/year2025/day03/part02/battery_bank.ml new file mode 100644 index 0000000..d7dc213 --- /dev/null +++ b/ocaml/lib/year2025/day03/part02/battery_bank.ml @@ -0,0 +1,77 @@ +open Battery + +module BatteryBank = struct + type t = Battery.t list + + type highest = {one: Battery.t option; two: Battery.t option} + + let rec highest_joltage bb = + assert (List.length bb > 0) ; + match highest_joltage_aux {one= None; two= None} bb with + | {one= None; two= None} -> + 0 + | {one= Some x; two= 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 + | {one= None; two= None} -> + {one= Some (Battery.of_int 0); two= Some elt} + | {one= Some first; two= None} -> + {one= Some first; two= Some elt} + | {one= None; two= Some second} -> + {one= Some second; two= Some elt} + | {one= Some first; two= Some second} -> + if elt > second then {one= Some first; two= Some elt} + else {one= Some first; two= Some second} ) + | h :: t -> + highest_joltage_aux + ( match acc with + | {one= None; two= None} -> + {one= Some h; two= None} + | {one= Some first; two= None} -> + let second = Battery.of_int 0 in + swap_if_higher first second h + | {one= Some first; two= 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 -> + {one= Some considering; two= None} + | false, true -> + {one= Some first; two= Some considering} + | true, false -> + failwith "[second] should never be greater than [first]" + | false, false -> + {one= Some first; two= 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/ocaml/lib/year2025/day03/part02/battery_bank.mli b/ocaml/lib/year2025/day03/part02/battery_bank.mli new file mode 100644 index 0000000..bffc4cb --- /dev/null +++ b/ocaml/lib/year2025/day03/part02/battery_bank.mli @@ -0,0 +1,18 @@ +open Battery + +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 diff --git a/ocaml/lib/year2025/day03/part02/solver.ml b/ocaml/lib/year2025/day03/part02/solver.ml new file mode 100644 index 0000000..4a06e83 --- /dev/null +++ b/ocaml/lib/year2025/day03/part02/solver.ml @@ -0,0 +1,23 @@ +open Battery_bank + +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/ocaml/lib/year2025/day03/part02/solver.mli b/ocaml/lib/year2025/day03/part02/solver.mli new file mode 100644 index 0000000..93d3b98 --- /dev/null +++ b/ocaml/lib/year2025/day03/part02/solver.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. *) -- cgit v1.2.3