在ocaml中查找给定数量的足球比赛的所有排列

时间:2019-04-07 13:09:52

标签: recursion ocaml permutation

我必须编写函数系列:int-> int->结果列表列表,因此第一个int表示游戏数,第二个int表示积分。

我已经通过创建所有排列并过滤列表来考虑经验解决方案,但是我认为这在ocaml非常脏的解决方案中包含很多代码行。而且我找不到解决该问题的另一种方法。

给出了以下类型

type result = Win (* 3 points *)
| Draw (* 1 point *)
| Loss (* 0 points *)

所以如果我打电话

series 3 4

解决方案应该是:

[[Win ;Draw ;Loss]; [Win ;Loss ;Draw]; [Draw ;Win ;Loss];
[Draw ;Loss ;Win]; [Loss ;Win ;Draw]; [Loss ;Draw ;Win]]

也许有人可以给我提示或代码示例,以开始操作。

2 个答案:

答案 0 :(得分:0)

考虑采用series n (n / 2)形式的调用,并考虑所有游戏均为DrawLoss的情况。在这些限制下,答案的数量与2^n/sqrt(n)成比例。 (在线上的人是从斯特林的近似中得到的。)

这不包括任何人赢得比赛的系列赛。因此,实际结果列表通常会更长。

我得出的结论是,可能的答案数量巨大,因此您的实际案例将很小。

如果您的实际情况很小,则使用蛮力方法可能没有问题。

与您的主张相反,蛮力代码通常很短且易于理解。

您可以轻松地编写一个函数,以列出从n提取的所有长度为Win, Lose, Draw的可能序列。然后,您可以过滤它们以获得正确的总和。渐近地,由于上述接近指数的行为,这可能只比最快的算法差一点。

答案 1 :(得分:0)

一个简单的递归解决方案将遵循这种方式:

  • 如果要玩0场游戏,要赚取0点,那么就只有一个(空)解决方案
  • 如果要玩0场比赛,并且要赚取1点或更多积分,那就没有解决办法。
  • 否则,必须在p个游戏中获得g分:通过添加{{1 }}。如果是p,则可以将g-1添加到Loss游戏中的p>=1的任何解决方案中;如果是Draw,则也可能以p-1