置换生成器函数F#

时间:2010-09-10 23:41:32

标签: f# permutation

我需要生成1..n x 1..n的所有不同排列的列表,其中第一个值不等于第二个 (即产生3 - > [(3,2)::(3,1)::(2,3)::(2,1)::(1,3)::(1,2)] < / p>

确切的情况是你有一个对象池(卡片),每个玩家都有一个。如果一名牌手被发牌,那么其他牌手就不会被发牌(暂时忽略套牌,如果必须的话,我会让1-52牌照到实际的牌上)

我想出了以下看起来很混乱的内容

 let  GenerateTuples (numcards: int) =
    let rec cellmaker (cardsleft: int) (cardval:int) = 
        if cardval = cardsleft  then (if cardval <= 0  then []  else cellmaker cardsleft (cardval-1) ) elif cardval <= 0  then [] else (cardsleft, cardval) :: cellmaker cardsleft (cardval-1)
    let rec generatelists (cardsleft:int) =
        cellmaker cardsleft numcards @ (if cardsleft > 1 then generatelists (cardsleft-1) else [])
    generatelists numcards

有更好的方法吗?

2 个答案:

答案 0 :(得分:6)

您可以使用列表推导轻松完成:

let GenerateTuples (n:int) =
    [for i in 1..n do for j in 1..n do if i <> j then yield (i,j)]

答案 1 :(得分:0)

这个问题最好被看作是一个矩阵问题,而命令式解决方案的嵌套“for”循环可以在功能上完成。

let Permute n =
let rec Aux (x,y) =
    if (x,y) = (n,n) then
        []
    else
        let nextTuple = if y = n then ((x + 1),1) else (x,(y + 1))
        if x = y then
            Aux nextTuple
        else
            (x,y)::(Aux nextTuple)
Aux (1,1)

这不是尾递归的,所以在我的机器上得到大约n = 500的堆栈溢出。使这个函数尾递归几乎是微不足道的。

时间非常有趣。这个函数(尾递归版)比原版多50%,而命令式解决方案再次花了大约3倍的时间!是的 - 最初的功能解决方案是最快的,这是下一个最快的,而命令式列表理解是最慢的,大约1 :: 1.5 :: 4。测试了各种各样的数据集。