Reputation: 983
I am new to ocaml and trying to write some code to generate all lists of number between two value.
For example, if I call this function generate
, I want to obtain something like this :
let generate ~min ~max ~length (* Maybe other arguments *) =
(* The code *)
;;
generate ~min:0 ~max:3 ~length:4;;
Should return
[
[0;0;0];
[1;0;0];
[2;0;0];
[3;0;0];
[0;1;0];
And so on, to
[3;2;3];
[0;3;3];
[1;3;3];
[2;3;3];
[3;3;3];
]
I already tried code like this :
open Core.Std;;
type next_list =
| Complete of int list
| Partial of int list
| Result of (int array) list
;;
let rec next ~r ~min ~max ~l =
let detox = function | Partial a -> a | _ -> assert false in
match l with
| Partial (hd :: tl) when hd <= max -> Partial (hd + 1 :: tl)
| Partial (hd :: tl) when hd = max + 1 -> next ~r ~min ~max
~l:(Partial (min :: (detox (next ~r ~min ~max ~l:(Partial tl))) ))
| Complete (hd :: tl) when hd <= max -> next ~r:([l] :: r) ~min ~max
~l:(Complete (hd + 1 :: tl))
| Complete (hd :: tl) when hd = max + 1 -> next ~r ~min ~max
~l:(Complete (min :: (detox (next ~r ~min ~max ~l:(Partial tl)))))
(*| Partial [] -> next ~r ~min ~max ~l:(Result r)*)
| Result a -> Result a
It may be spread around several functions if necessary, that is not a problem.
I am also interested by non ocaml code or idea.
Thanks for your help.
This is my first question on Stackoverflow, do not hesitate to say if my question is unclear.
Upvotes: 3
Views: 679
Reputation: 4431
here some solution : First, let's define that takes 2 lists l1 & l2 as input and that produces a list of list, where each element is l2 augmented by 1 element of l1 :
let enumerate l ll = List.fold ~init:[] ~f:(fun op x -> (x::ll)::op) l;;
enumerate [0;1;2;3] [4;5;6];; - : int list list = [[3; 4; 5; 6]; [2; 4; 5; 6]; [1; 4; 5; 6]; [0; 4; 5; 6]]
Now generate :
let rec generate length ll =
if length=1 then List.fold ~init:[] ~f:(fun op x -> [x]::op) ll
else
let result = generate (length-1) ll in
List.fold ~init:[] ~f:(fun op x -> (enumerate ll x)@op) result;;
and usage is as follows :
generate 2 [1;2;3];; (* instead of generate ~min:1 ~max:3 ~length:2 *)
Some explanation : List.fold ~init:[] ~f:(fun op x -> [x]::op) ll => this creates the initial list of list (singleton)
And the second : takes each of the list of length -1 and performs the enumeration.
Upvotes: 1
Reputation: 9377
Here's a hint:
let count_prefix low high lists =
???
let generate min max length =
let rec recur low high len =
if len = 0 then []
else count_prefix low high (recur low high (len - 1)) in
recur min max length
count_prefix
should return a list that is the elements of lists
prefixed with the numbers low
to high
. If lists
is empty, it should return a list of lists containing the numbers low
to high
. That is:
count_prefix 0 3 [] => [[0]; [1]; [2]]
count_prefix 0 3 [[10];[20]] => [[0; 10]; [0; 20]; [1; 10]; [1; 20]; [2; 10]; [2; 20]]
Fill in the definition of count_prefix
.
Upvotes: 0