blob: a1bdc00c65ed3fba437b25d6adca0ade73c70833 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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"]
|