我正致力于在扑克中获胜的计算概率(持有德州扑克游戏)。为此,我必须制作一个功能,从手牌的两张牌和桌子上的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
答案 0 :(得分:0)
在我看来,这是一个典型的问题示例,其中考虑更一般的情况使其更容易。考虑在n
张牌中找到l
牌的所有组合的问题。
为简单起见,我会认为card
只是通用'a
。另外,我不会在手和桌子之间做任何区别,我只是将它们视为单个列表。将两者分开可能会带来更好的解决方案,但却不易理解: - )
因此,您将拥有一个函数comb n l
,该函数返回列表n
中l
元素的所有组合的列表(因此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]]