Skip to content

Instantly share code, notes, and snippets.

@chris-taylor
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chris-taylor/8699351 to your computer and use it in GitHub Desktop.
Save chris-taylor/8699351 to your computer and use it in GitHub Desktop.
(* Define monadic operations for a list *)
let return x = [x]
let (>>=) lst f = List.concat (List.map f lst)
(* Generate the combinations of k distinct objects from a list *)
(* Simple version
let rec combnk k lst =
if k = 0 then
[[]]
else
let rec inner = function
| [] -> []
| x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) :: inner xs in
List.concat (inner lst)
*)
let rec combnk k lst =
if k = 0 then
[[]]
else
match lst with
| [] -> []
| x :: xs -> (combnk (k - 1) xs >>= fun comb ->
return (x :: comb)) @ combnk k xs
(* Set difference for lists *)
let rec set_diff xs ys = match xs with
| [] -> []
| h :: t -> if List.mem h ys then
set_diff t ys
else
h :: set_diff t ys
(*
Sort a list into subgroups of specific sizes. For example,
# group ["a";"b";"c";"d"] [2;1];;
- : string list list list =
[[["a"; "b"]; ["c"]]; [["a"; "c"]; ["b"]]; [["b"; "c"]; ["a"]];
[["a"; "b"]; ["d"]]; [["a"; "c"]; ["d"]]; [["b"; "c"]; ["d"]];
[["a"; "d"]; ["b"]]; [["b"; "d"]; ["a"]]; [["a"; "d"]; ["c"]];
[["b"; "d"]; ["c"]]; [["c"; "d"]; ["a"]]; [["c"; "d"]; ["b"]]]
*)
let rec group lst sizes = match sizes with
| [] -> [[]]
| h :: t -> combnk h lst >>= fun grp ->
group (set_diff lst grp) t >>= fun grps ->
return (grp :: grps)
(* I belive that the non-monadic code looks something like this:
let rec group (lst : 'a list) (sizes : int list) : 'a list list list =
match sizes with
| [] -> [[]]
| h :: t -> let f gr = List.map (fun z -> gr :: z) (group (set_diff lst gr) t) in
let grps = combnk h lst in
List.concat (List.map f grps)
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment