let enum_cartesian_product ll = let pool = Array.map Array.of_list (Array.of_list ll) in let n = Array.length pool in let indices = Array.make n 0 and lengths = Array.map (fun a -> Array.length a - 1) pool in let rec update_indices = function | i when indices.(i) <> lengths.(i) -> indices.(i) <- indices.(i) + 1 | 0 -> raise BatEnum.No_more_elements | i -> indices.(i) <- 0; update_indices (i - 1) in let is_first = ref true in let next () = if !is_first then is_first := false else update_indices (n - 1); Array.to_list (BatArray.map2 Array.get pool indices) in BatEnum.from next let combinations l r = if r <= 0 then invalid_arg "r must be positive"; let pool = Array.of_list l and indices = Array.init r (fun x -> x) in let n = Array.length pool in let rec next_i = function | i when indices.(i) <> i + n - r -> i | 0 -> raise BatEnum.No_more_elements | i -> next_i (i - 1) in let is_first = ref true in let next () = if !is_first then is_first := false else begin let i = next_i (r - 1) in indices.(i) <- indices.(i) + 1; for j = i + 1 to r - 1 do indices.(j) <- indices.(j - 1) + 1 done end; map (Array.get pool) (Array.to_list indices) in BatEnum.from next