algorithm - OCaml 中的循环算法

标签 algorithm ocaml round-robin

这是What's the grouping plan so that every two people are grouped together just once?的后续问题

基本上,我实现了 Round robin algorithm .


通过该算法,它可以生成对列表,其中每个可能的元素对都恰好分组在一起一次。

例如,我们有a、b、c、d,那么

第一天,我们就这样做

a b
cd

然后我们像[(a,c);(b,d)]那样分组。

然后我们像这样顺时针舍入它

a c
db

然后我们像[(a,d);(c,b)]那样分组。

然后我们像这样顺时针舍入它

a d
b c

然后我们像[(a,b);(d,c)]那样分组。

(注意,a 始终是固定的。)

终于可以了

[(a,c);(b,d)]
[(a,d);(c,b)]
[(a,b);(d,c)]


以下是 ocaml 代码:

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)

按照算法,代码非常简单。 有更好的实现吗?

最佳答案

let round_robin ~nplayers ~round i =
  (* only works for an even number of players *)
  assert (nplayers mod 2 = 0);
  assert (0 <= round && round < nplayers - 1);
  (* i is the position of a match,
     at each round there are nplayers/2 matches *)
  assert (0 <= i && i < nplayers / 2);
  let last = nplayers - 1 in
  let player pos =
    if pos = last then last
    else (pos + round) mod last
  in
  (player i, player (last - i))

let all_matches nplayers =
  Array.init (nplayers - 1) (fun round ->
    Array.init (nplayers / 2) (fun i ->
      round_robin ~nplayers ~round i))

let _ = all_matches 6;;
(**
[|[|(0, 5); (1, 4); (2, 3)|];
  [|(1, 5); (2, 0); (3, 4)|];
  [|(2, 5); (3, 1); (4, 0)|];
  [|(3, 5); (4, 2); (0, 1)|];
  [|(4, 5); (0, 3); (1, 2)|]|]
*)

关于algorithm - OCaml 中的循环算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20332184/

相关文章:

operating-system - 在就绪队列只有一个进程且使用循环调度的系统中是否发生上下文切换?

java - 循环法 Java : Execution Process Not Occur Based on roundrobin algorithm

algorithm - 使用以下算法找到近似最小值的预期更新次数

algorithm - 使用 2 个数字求和的方法数

functional-programming - 在OCaml中使用Array实现Stack时如何保持多态性?

performance - OCaml 优化技术

algorithm - 如何最快地检查点(3D)是否在点集给出的凸包内

algorithm - 我怎样才能为此制定准确的复发率?

.net - 获取模式匹配中可区分联合的大小写标识符

c - 比赛排类表C算法