This is the followup question of What's the grouping plan so that every two people are grouped together just once?
Basically, I implemented the Round robin algorithm.
By the algorithm, it can generate pairs list where each possible pair of elements are grouped together exactly once.
For example, we have a, b, c, d
, then
On first day, we do
a
b
c d
Then we group like [(a,c);(b,d)].
Then we round it clockwise like
a
c
d b
Then we group like [(a,d);(c,b)].
Then we round it clockwise like
a
d
b c
Then we group like [(a,b);(d,c)].
(Note, a
is fixed all the time.)
Finally I can get
[(a,c);(b,d)]
[(a,d);(c,b)]
[(a,b);(d,c)]
Here are the ocaml code:
let split = List.fold_left (fun (l1, l2) x -> (l2, x::l1)) ([], [])
let round l1 l2 =
match List.rev l1, l2 with
| _, [] | [], _ -> raise Cant_round
| hd1::tl1, hd2::tl2 ->
hd2::(List.rev tl1), List.rev (hd1::List.rev tl2)
let rec robin fixed stopper acc = function
| _, [] | [], _ -> raise Cant_robin
| l1, (hd2::tl2 as l2) ->
if hd2 = stopper then acc
else robin fixed stopper ((List.combine (fixed::l1) l2)::acc) (round l1 l2)
let round_robin = function
| [] | _::[] -> raise Cant_round_robin
| hd::tl ->
let l1, l2 = in
match split tl with
| _, [] -> raise Cant_round_robin
| l1, (hd2::_ as l2) ->
robin hd hd2 ((List.combine (hd::l1) l2)::[]) (round l1 l2)
The code is quite straight forward following the algorithm. Is there a better implmentation?