summaryrefslogtreecommitdiff
path: root/ocaml/lib/domain/range.ml
diff options
context:
space:
mode:
authorDJ O'Leary <dijitol@proton.me>2026-06-26 18:04:09 +0200
committerDJ O'Leary <dijitol@proton.me>2026-06-26 18:04:09 +0200
commit6d8fb621d1e93b83786890d6d9cb6f0d8defa8ae (patch)
tree17c90d3984c114aa023600cc5bec6f6004b02243 /ocaml/lib/domain/range.ml
parentad4ea5ca4bc9f7540ee1d6a4fa2d881709dc6459 (diff)
refactor!: invert repo directory structure
now is language first
Diffstat (limited to 'ocaml/lib/domain/range.ml')
-rw-r--r--ocaml/lib/domain/range.ml67
1 files changed, 67 insertions, 0 deletions
diff --git a/ocaml/lib/domain/range.ml b/ocaml/lib/domain/range.ml
new file mode 100644
index 0000000..a1bdc00
--- /dev/null
+++ b/ocaml/lib/domain/range.ml
@@ -0,0 +1,67 @@
+module M : sig
+ type t
+
+ val of_string : string -> t option
+ (** [of_string s] is a range of integers if [s] is a string in the form ["%d-%d"]
+ or [None] otherwise. *)
+
+ val collect : t -> int list
+ (** [collect range] is a fully realised range as a list.
+ Example: ["1-5" |> of_string |> collect] is the list [\[1;2;3;4;5\]].
+ Example: ["5-1" |> of_string |> collect] is the list [\[5;4;3;2;1\]].*)
+
+ val pp : t -> string
+ (** [pp range] is a pretty-printed version of the range. *)
+end = struct
+ type t = int * int
+
+ let of_string s =
+ Scanf.sscanf_opt s "%d-%d" (fun start finish -> (start, finish))
+
+ let rec collect (start, finish) =
+ let collected =
+ match Int.compare start finish with
+ | -1 ->
+ collect_range_aux Int.succ ( > ) [] (start, finish)
+ | 0 ->
+ [start]
+ | 1 ->
+ collect_range_aux Int.pred ( < ) [] (start, finish)
+ | _ ->
+ assert false
+ in
+ List.rev collected
+
+ and collect_range_aux fn cmp lst (start, finish) =
+ if cmp start finish then lst
+ else collect_range_aux fn cmp (start :: lst) (fn start, finish)
+
+ let pp (start, finish) = string_of_int start ^ "-" ^ string_of_int finish
+end
+
+let%expect_test "incrementing range" =
+ match M.of_string "1-5" with
+ | None ->
+ [%expect.unreachable]
+ | Some range ->
+ let collected = M.collect range in
+ List.iter print_int collected ;
+ [%expect "12345"]
+
+let%expect_test "decrementing range" =
+ match M.of_string "5-1" with
+ | None ->
+ [%expect.unreachable]
+ | Some range ->
+ let collected = M.collect range in
+ List.iter print_int collected ;
+ [%expect "54321"]
+
+let%expect_test "one element range" =
+ match M.of_string "1-1" with
+ | None ->
+ [%expect.unreachable]
+ | Some range ->
+ let collected = M.collect range in
+ List.iter print_int collected ;
+ [%expect "1"]