mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
add CCInt.range{,',by} for iterating on integer ranges
This commit is contained in:
parent
47abc78a51
commit
e0287b9efe
2 changed files with 99 additions and 0 deletions
|
|
@ -39,6 +39,7 @@ let pow a b =
|
|||
|
||||
type 'a printer = Format.formatter -> 'a -> unit
|
||||
type 'a random_gen = Random.State.t -> 'a
|
||||
type 'a sequence = ('a -> unit) -> unit
|
||||
|
||||
let random n st = Random.State.int st n
|
||||
let random_small = random 100
|
||||
|
|
@ -96,6 +97,76 @@ let to_string_binary n =
|
|||
Q.int (fun n -> n = int_of_string (to_string_binary n))
|
||||
*)
|
||||
|
||||
let range_by ~step i j yield =
|
||||
let rec range i j yield =
|
||||
if i=j then yield i
|
||||
else (
|
||||
yield i;
|
||||
range (i+step) j yield
|
||||
)
|
||||
in
|
||||
if step = 0 then
|
||||
raise (Invalid_argument "CCList.range_by")
|
||||
else if (if step > 0 then i>j else i<j) then ()
|
||||
else range i ((j-i)/step*step + i) yield
|
||||
|
||||
(* note: the last test checks that no error occurs due to overflows. *)
|
||||
(*$= & ~printer:Q.Print.(list int)
|
||||
[0] (range_by ~step:1 0 0 |> Sequence.to_list)
|
||||
[] (range_by ~step:1 5 0 |> Sequence.to_list)
|
||||
[] (range_by ~step:2 1 0 |> Sequence.to_list)
|
||||
[0;2;4] (range_by ~step:2 0 4 |> Sequence.to_list)
|
||||
[0;2;4] (range_by ~step:2 0 5 |> Sequence.to_list)
|
||||
[0] (range_by ~step:~-1 0 0 |> Sequence.to_list)
|
||||
[] (range_by ~step:~-1 0 5 |> Sequence.to_list)
|
||||
[] (range_by ~step:~-2 0 1 |> Sequence.to_list)
|
||||
[5;3;1] (range_by ~step:~-2 5 1 |> Sequence.to_list)
|
||||
[5;3;1] (range_by ~step:~-2 5 0 |> Sequence.to_list)
|
||||
[0] (range_by ~step:max_int 0 2 |> Sequence.to_list)
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(pair small_int small_int) (fun (i,j) -> \
|
||||
let i = min i j and j = max i j in \
|
||||
CCList.equal CCInt.equal \
|
||||
(CCInt.range_by ~step:1 i j |> Sequence.to_list) \
|
||||
(CCInt.range i j |> Sequence.to_list) )
|
||||
*)
|
||||
|
||||
let range i j yield =
|
||||
let rec up i j yield =
|
||||
if i=j then yield i
|
||||
else (
|
||||
yield i;
|
||||
up (i+1) j yield
|
||||
)
|
||||
and down i j yield =
|
||||
if i=j then yield i
|
||||
else (
|
||||
yield i;
|
||||
down (i-1) j yield
|
||||
)
|
||||
in
|
||||
if i<=j then up i j yield else down i j yield
|
||||
|
||||
(*$= & ~printer:Q.Print.(list int)
|
||||
[0;1;2;3;4;5] (range 0 5 |> Sequence.to_list)
|
||||
[0] (range 0 0 |> Sequence.to_list)
|
||||
[5;4;3;2] (range 5 2 |> Sequence.to_list)
|
||||
*)
|
||||
|
||||
let range' i j yield =
|
||||
if i<j then range i (j-1) yield
|
||||
else if i=j then ()
|
||||
else range i (j+1) yield
|
||||
|
||||
(*$= & ~printer:Q.Print.(list int)
|
||||
[] (range' 0 0 |> Sequence.to_list)
|
||||
[0;1;2;3;4] (range' 0 5 |> Sequence.to_list)
|
||||
[5;4;3] (range' 5 2 |> Sequence.to_list)
|
||||
*)
|
||||
|
||||
|
||||
module Infix = struct
|
||||
let (=) = Pervasives.(=)
|
||||
let (<>) = Pervasives.(<>)
|
||||
|
|
@ -103,6 +174,8 @@ module Infix = struct
|
|||
let (>) = Pervasives.(>)
|
||||
let (<=) = Pervasives.(<=)
|
||||
let (>=) = Pervasives.(>=)
|
||||
let (--) = range
|
||||
let (--^) = range'
|
||||
end
|
||||
include Infix
|
||||
let min = min
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ val pow : t -> t -> t
|
|||
|
||||
type 'a printer = Format.formatter -> 'a -> unit
|
||||
type 'a random_gen = Random.State.t -> 'a
|
||||
type 'a sequence = ('a -> unit) -> unit
|
||||
|
||||
val random : int -> t random_gen
|
||||
val random_small : t random_gen
|
||||
|
|
@ -51,6 +52,23 @@ val min : t -> t -> t
|
|||
val max : t -> t -> t
|
||||
(** @since 0.17 *)
|
||||
|
||||
val range_by : step:t -> t -> t -> t sequence
|
||||
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
|
||||
where the difference between successive elements is [step].
|
||||
use a negative [step] for a decreasing list.
|
||||
@raise Invalid_argument if [step=0]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val range : t -> t -> t sequence
|
||||
(** [range i j] iterates on integers from [i] to [j] included . It works
|
||||
both for decreasing and increasing ranges
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val range' : t -> t -> t sequence
|
||||
(** Same as {!range} but the second bound is excluded.
|
||||
For instance [range' 0 5 = Sequence.of_list [0;1;2;3;4]]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
(** {2 Infix Operators}
|
||||
|
||||
@since 0.17 *)
|
||||
|
|
@ -72,6 +90,14 @@ module Infix : sig
|
|||
|
||||
val (>=) : t -> t -> bool
|
||||
(** @since 0.17 *)
|
||||
|
||||
val (--) : t -> t -> t sequence
|
||||
(** Alias to {!range}
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val (--^) : t -> t -> t sequence
|
||||
(** Alias to {!range'}
|
||||
@since NEXT_RELEASE *)
|
||||
end
|
||||
|
||||
include module type of Infix
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue