summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ O'Leary <dijitol@proton.me>2025-12-07 21:16:13 +0100
committerDJ O'Leary <dijitol@proton.me>2025-12-07 21:16:13 +0100
commit373c53ce69b08c0cf2076dd12ba8b586199a5663 (patch)
tree821c466a8a5c430150aec0b1bdac2a9d77a57aab
parent661ce5a9f27b25cae3672087bc8d1f8eac24ea06 (diff)
refactor(matrix): convert matrix into domain module
-rw-r--r--2025/ocaml/lib/application/d04p01.ml106
-rw-r--r--2025/ocaml/lib/domain/matrix.ml150
2 files changed, 152 insertions, 104 deletions
diff --git a/2025/ocaml/lib/application/d04p01.ml b/2025/ocaml/lib/application/d04p01.ml
index 2cc5f5d..4bf38ad 100644
--- a/2025/ocaml/lib/application/d04p01.ml
+++ b/2025/ocaml/lib/application/d04p01.ml
@@ -1,106 +1,4 @@
-(** [input_to_matrix input] is a 2D Array where each line of the [input] is
- a row and each character in that line is a column.
- Requires: all lines in input are of equal length. *)
-let input_to_matrix input =
- let lines =
- input |> String.split_on_char '\n'
- |> List.filter_map (fun line ->
- let trimmed = String.trim line in
- if trimmed <> "" then Some trimmed else None )
- in
- let row_count = List.length lines in
- let column_count =
- match List.nth_opt lines 1 with
- | None ->
- failwith "first line should not be empty"
- | Some line ->
- String.length line
- in
- let matrix = Array.make_matrix column_count row_count "" in
- List.iteri
- (fun y line ->
- String.iteri (fun x char -> matrix.(x).(y) <- Char.escaped char) line )
- lines ;
- matrix
-
-(** [pp_matrix matrix] is the [input] that was used to create the [matrix]
- via [input_to_matrix input]. *)
-let pp_matrix matrix =
- let row_count = Array.length matrix in
- let column_count = Array.length matrix.(0) in
- let matrix' = Array.make_matrix row_count column_count "" in
- Array.iteri
- (fun x row -> Array.iteri (fun y c -> matrix'.(y).(x) <- c) row)
- matrix ;
- matrix'
- |> Array.map @@ Array.fold_left (fun acc c -> acc ^ c) ""
- |> Array.fold_left
- (fun acc line -> if acc = "" then line else acc ^ "\n" ^ line)
- ""
-
let solve input () =
- let matrix = input |> input_to_matrix in
- Logs.debug (fun m -> m "\n%s" @@ pp_matrix matrix) ;
+ let matrix = Domain.Matrix.M.of_string input in
+ Logs.debug (fun m -> m "\n%s" @@ Domain.Matrix.M.pp (fun s -> s) matrix) ;
0
-
-let%expect_test "matrix created from input is pretty-printed as the same matrix"
- =
- let example =
- {|..@@.@@@@.
-@@@.@.@.@@
-@@@@@.@.@@
-@.@@@@..@.
-@@.@@@@.@@
-.@@@@@@@.@
-.@.@.@.@@@
-@.@@@.@@@@
-.@@@@@@@@.
-@.@.@@@.@.|}
- in
- print_string @@ pp_matrix @@ input_to_matrix example ;
- [%expect
- {|..@@.@@@@.
-@@@.@.@.@@
-@@@@@.@.@@
-@.@@@@..@.
-@@.@@@@.@@
-.@@@@@@@.@
-.@.@.@.@@@
-@.@@@.@@@@
-.@@@@@@@@.
-@.@.@@@.@.|}]
-
-let%expect_test "direct access of the matrix is in form matrix.(x).(y)" =
- let example =
- {|..@@.@@@@.
-@@@.@.@.@@
-@@@@@.@.@@
-@.@@@@..@.
-@@.@@@@.@@
-.@@@@@@@.@
-.@.@.@.@@@
-@.@@@.@@@@
-.@@@@@@@@.
-@.@.@@@.@.|}
- in
- let matrix = input_to_matrix example in
- print_string matrix.(0).(0) ;
- [%expect "."] ;
- print_string matrix.(1).(0) ;
- [%expect "."] ;
- print_string matrix.(2).(0) ;
- [%expect "@"] ;
- print_string matrix.(3).(0) ;
- [%expect "@"] ;
- print_string matrix.(4).(0) ;
- [%expect "."] ;
- print_string matrix.(5).(0) ;
- [%expect "@"] ;
- print_string matrix.(6).(0) ;
- [%expect "@"] ;
- print_string matrix.(7).(0) ;
- [%expect "@"] ;
- print_string matrix.(8).(0) ;
- [%expect "@"] ;
- print_string matrix.(9).(0) ;
- [%expect "."]
diff --git a/2025/ocaml/lib/domain/matrix.ml b/2025/ocaml/lib/domain/matrix.ml
new file mode 100644
index 0000000..bb703fc
--- /dev/null
+++ b/2025/ocaml/lib/domain/matrix.ml
@@ -0,0 +1,150 @@
+module M : sig
+ type 'a t = 'a array array
+
+ val empty : int -> int -> 'a -> 'a t
+ (** [empty rows columns initial] is an empty 2D array of size [rows] * [columns]
+ where each element in the array is initialized to [initial]. *)
+
+ val of_list : 'a list list -> 'a t
+ (** *)
+
+ val of_string : string -> string t
+ (** [of_string str] is a 2D array where every character is an element. *)
+
+ val get : 'a t -> int -> int -> 'a
+ (** [get matrix x y] is an alias for [matrix.(y).(x)] *)
+
+ val pp : ('a -> string) -> 'a t -> string
+ (** [pp matrix string_of_elt] is the string representation of the [matrix]
+ where [string_of_elt] is called on each element. *)
+end = struct
+ type 'a t = 'a array array
+
+ let empty cols rows initial = Array.make_matrix cols rows initial
+
+ let of_list lst = Array.of_list @@ List.map Array.of_list lst
+
+ let of_string str =
+ let lines =
+ str |> String.split_on_char '\n'
+ |> List.filter_map (fun line ->
+ let trimmed = String.trim line in
+ if trimmed <> "" then Some trimmed else None )
+ in
+ let char_lst =
+ List.map
+ (fun s -> s |> String.to_seq |> List.of_seq |> List.map Char.escaped)
+ lines
+ in
+ of_list char_lst
+
+ let get matrix x y = matrix.(y).(x)
+
+ let pp string_of_elt matrix =
+ Array.fold_left
+ (fun col_acc arr ->
+ let row =
+ Array.fold_left
+ (fun row_acc elt -> row_acc ^ string_of_elt elt)
+ "" arr
+ in
+ if col_acc = "" then row else col_acc ^ "\n" ^ row )
+ "" matrix
+end
+
+let%expect_test "matrix created from input is pretty-printed as the same matrix"
+ =
+ let example =
+ {|..@@.@@@@.
+@@@.@.@.@@
+@@@@@.@.@@
+@.@@@@..@.
+@@.@@@@.@@
+.@@@@@@@.@
+.@.@.@.@@@
+@.@@@.@@@@
+.@@@@@@@@.
+@.@.@@@.@.|}
+ in
+ print_string @@ M.pp (fun s -> s) @@ M.of_string example ;
+ [%expect
+ {|..@@.@@@@.
+@@@.@.@.@@
+@@@@@.@.@@
+@.@@@@..@.
+@@.@@@@.@@
+.@@@@@@@.@
+.@.@.@.@@@
+@.@@@.@@@@
+.@@@@@@@@.
+@.@.@@@.@.|}]
+
+let%expect_test "direct access of the matrix is in form matrix.(y).(x)" =
+ let example =
+ {|..@@.@@@@.
+@@@.@.@.@@
+@@@@@.@.@@
+@.@@@@..@.
+@@.@@@@.@@
+.@@@@@@@.@
+.@.@.@.@@@
+@.@@@.@@@@
+.@@@@@@@@.
+@.@.@@@.@.|}
+ in
+ let matrix = M.of_string example in
+ print_string matrix.(0).(0) ;
+ [%expect "."] ;
+ print_string matrix.(0).(1) ;
+ [%expect "."] ;
+ print_string matrix.(0).(2) ;
+ [%expect "@"] ;
+ print_string matrix.(0).(3) ;
+ [%expect "@"] ;
+ print_string matrix.(0).(4) ;
+ [%expect "."] ;
+ print_string matrix.(0).(5) ;
+ [%expect "@"] ;
+ print_string matrix.(0).(6) ;
+ [%expect "@"] ;
+ print_string matrix.(0).(7) ;
+ [%expect "@"] ;
+ print_string matrix.(0).(8) ;
+ [%expect "@"] ;
+ print_string matrix.(0).(9) ;
+ [%expect "."]
+
+let%expect_test "[M.get matrix x y] is an alias for [matrix.(y).(x)]" =
+ let example =
+ {|..@@.@@@@.
+@@@.@.@.@@
+@@@@@.@.@@
+@.@@@@..@.
+@@.@@@@.@@
+.@@@@@@@.@
+.@.@.@.@@@
+@.@@@.@@@@
+.@@@@@@@@.
+@.@.@@@.@.|}
+ in
+ let matrix = M.of_string example in
+ print_string @@ M.get matrix 0 0 ;
+ [%expect "."] ;
+ print_string @@ M.get matrix 1 0 ;
+ [%expect "."] ;
+ print_string @@ M.get matrix 2 0 ;
+ [%expect "@"] ;
+ print_string @@ M.get matrix 3 0 ;
+ [%expect "@"] ;
+ print_string @@ M.get matrix 4 0 ;
+ [%expect "."] ;
+ print_string @@ M.get matrix 5 0 ;
+ [%expect "@"] ;
+ print_string @@ M.get matrix 6 0 ;
+ [%expect "@"] ;
+ print_string @@ M.get matrix 7 0 ;
+ [%expect "@"] ;
+ print_string @@ M.get matrix 8 0 ;
+ [%expect "@"] ;
+ print_string @@ M.get matrix 9 0 ;
+ [%expect "."]