spacepaste

  1.  
  2. let enum_cartesian_product ll =
  3. let pool = Array.map Array.of_list (Array.of_list ll) in
  4. let n = Array.length pool in
  5. let indices = Array.make n 0
  6. and lengths = Array.map (fun a -> Array.length a - 1) pool in
  7. let rec update_indices = function
  8. | i when indices.(i) <> lengths.(i) ->
  9. indices.(i) <- indices.(i) + 1
  10. | 0 -> raise BatEnum.No_more_elements
  11. | i ->
  12. indices.(i) <- 0; update_indices (i - 1)
  13. in
  14. let is_first = ref true in
  15. let next () =
  16. if !is_first then
  17. is_first := false
  18. else update_indices (n - 1);
  19. Array.to_list (BatArray.map2 Array.get pool indices)
  20. in
  21. BatEnum.from next
  22. let combinations l r =
  23. if r <= 0 then
  24. invalid_arg "r must be positive";
  25. let pool = Array.of_list l
  26. and indices = Array.init r (fun x -> x) in
  27. let n = Array.length pool in
  28. let rec next_i = function
  29. | i when indices.(i) <> i + n - r -> i
  30. | 0 -> raise BatEnum.No_more_elements
  31. | i -> next_i (i - 1)
  32. in
  33. let is_first = ref true in
  34. let next () =
  35. if !is_first then
  36. is_first := false
  37. else begin
  38. let i = next_i (r - 1) in
  39. indices.(i) <- indices.(i) + 1;
  40. for j = i + 1 to r - 1 do indices.(j) <- indices.(j - 1) + 1 done
  41. end;
  42. map (Array.get pool) (Array.to_list indices)
  43. in
  44. BatEnum.from next
  45.