从ocaml中的集合生成可能子集的列表

时间:2017-12-31 10:18:19

标签: ocaml poker probability-theory

我正致力于在扑克中获胜的计算概率(持有德州扑克游戏)。为此,我必须制作一个功能,从手牌的两张牌和桌子上的3张或4张或5张牌中返回5张牌的每一个组合。 我想在桌子上的牌数上做一场比赛。所以,如果我有3个,那么唯一的五张牌就是手中的两张牌+桌子上的3张牌,但是一旦我桌子上有4张或5张牌,我将有6到21张组合,所以我开始了方式

let compute_comb (d:donne) (t:table) =
  let l = listTable t in
  let l_size = List.length l in
  match l_size with
  |3 -> listCartes d t
  |4 -> 

请注意,donne是一个定义类似type donne = card*card的类型 和table的定义类似于type table = card*card*card*card*card

1 个答案:

答案 0 :(得分:0)

在我看来,这是一个典型的问题示例,其中考虑更一般的情况使其更容易。考虑在n张牌中找到l牌的所有组合的问题。

为简单起见,我会认为card只是通用'a。另外,我不会在手和桌子之间做任何区别,我只是将它们视为单个列表。将两者分开可能会带来更好的解决方案,但却不易理解: - )

因此,您将拥有一个函数comb n l,该函数返回列表nl元素的所有组合的列表(因此comb返回'a list list 1}})。让我们递归地做:

首先,如果n大于l的长度,请放弃:

exception NotEnoughElement of int*int
let rec comb n l = 
let length_l = List.length l in
if n > length_l
  raise (NotEnoughElement (n, length_l))
else

现在我们确定n是合适的,根据n有三种情况需要考虑:if n = 0,然后返回一个空列表

match n with
| 0 -> []

如果n是列表的大小,则没有选择:唯一合适的子列表是......列表本身(在您card开启的情况下,这类似于桌子)。请注意,我们会返回一个包含l的列表,以履行我们的同意comb返回所有子列表的列表。

| _ when n == length_l -> [l]

最后,如果n小于l的长度,我们可以选择:我们要么取l的头,要么我们不这样做。

| _ -> 

如果我们选择l的头部,那么我们必须在n-1的尾部搜索l个元素的组合,然后我们追加l的头部对所有这些子组合。要执行追加,请执行此功能

  let app_head sublist = (List.hd l) :: sublist in

如何在n-1的尾部采用l元素的组合?好吧,我们有人说comb n l会返回n中所有l组合的列表,因此我们可以使用此“合同”:

  let sublists = comb (n-1) (List.tl l) in

现在,让我们进行追加,List模块提供了一个map函数,它将函数应用于列表的所有元素,我们可以使用我们的app_head函数:

  let combination_head_taken = List.map app_head sublists in

现在,如果我们不采取行动,那么我们仍然需要在n的尾部搜索l个元素。我们再一次在comb

上使用我们的聚合
  let combination_head_not_taken = comb (n-1) (List.tl l) in

然后,只需连接两个子类中生成的组合:

  combination_head_taken @ combination_head_not_taken

然后你可以玩utop(假设你在comb.ml中写了这个函数):

$ utop
# #use "comb.ml";;
# let hand = [1;2;3;4;5];;
# comb 3 hand;;
- : int list list = [[2; 3; 4; 5]; [1; 3; 4; 5]; [1; 2; 4; 5]; [1; 2; 3; 5]]