-
Notifications
You must be signed in to change notification settings - Fork 0
/
27.ml
62 lines (53 loc) · 2.03 KB
/
27.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(*Group the elements of a set into disjoint subsets. (medium)
In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.
Generalize the above function in a way that we can specify a list of group sizes and the function will return a list of groups.*)
(*
# 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 group xs ns =
let extract_remove n xs =
let rec each base remacc acc xs n = match xs with
| [] -> acc
| x :: xs ->
if n = 1 then each base (x::remacc) ((x::base, remacc @ xs)::acc) xs n
else each (x::base) remacc (each base (x::remacc) acc xs n) xs (n-1) in
List.map (fun y -> (List.rev (fst y), snd y)) (each [] [] [] xs n) in
let rec prepend_all acc base news = match news with
| [] -> acc
| (nbase, ntodo) :: news -> prepend_all ((base @ [nbase], ntodo)::acc) base news in
let rec expand acc xs n = match xs with
| [] -> acc
| (base, todo) :: xs ->
let news = extract_remove n todo in
expand (prepend_all acc base news) xs n in
let rec aux acc ns = match ns with
| [] -> acc
| n :: ns -> aux (expand [] acc n) ns in
List.fold_left (fun l x -> let (r, _) = x in r::l) [] (aux [([], xs)] ns);;
group ["a";"b";"c";"d"] [2;2];;
(*
abcd
takes ([[a;b]; [c]], [d])
([[a;b]; [c]], todo)
[[a;b]; [d]]
[[a;c]; [b]]
[[a;c]; [d]]
ad b
ad c
[([], [a;b;c;d])]
(* 2 *)
[([[a;d]], [c;b]); ([[a;c]], [b;d]);
([[a;b]], [c;d]); ([[b;d]], [c;a]);
([[b;c]], [a;d]); ([[c;d]], [b;a])]
(* 1 *)
[([[a;d];[c]], [b]); ([[a;c];b], [d]);
([[a;b];[c]], [d]); ([[b;d];c], [a]);
([[b;c];[a]], [d]); ([[c;d];b], [a]);
([[a;d];[b]], [c]); ([[a;c];d], [b]);
([[a;b];[d]], [c]); ([[b;d];a], [c]);
([[b;c];[d]], [a]); ([[c;d];a], [b])]*)