排列生成器函数 F#

发布于 2024-09-18 07:29:08 字数 751 浏览 7 评论 0 原文

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

]确切的情况是,你有一堆物体(牌),每个玩家都会发一张牌,如果给一个玩家发一张牌,那么其他玩家就不能发这张牌(暂时忽略花色,如果有必要的话我会的。为 1-52 制作一个 lut 来映射到实际的卡片)

我想出了以下内容,充其量看起来很混乱,

 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

有更好的方法吗?

I need to generate a list of all distinct permutations of 1..n x 1..n where teh first value does not equal the second
(i.e. generate 3 -> [(3,2):: (3,1):: (2,3) ::(2,1)::(1,3)::(1,2)]

the exact scenario is you have a pool of objects(cards) and one is dealt to each player. If a player is dealt a card, no other player can be dealt that card(ignore suits for the time being, if I have to I will make a lut for 1-52 to map to the actual cards)

I came up with the following which seems messy at best

 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

is there a better way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相思碎 2024-09-25 07:29:09

该问题最好被视为一个矩阵问题,并且命令式解决方案的嵌套“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。在各种数据集上进行了测试。

The problem is best seen as a matrix problem, and the nested "for" loops of the imperative solution can be done functionally.

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)

This is not tail-recursive, so get's a stack overflow at approx n = 500, on my machine. It is almost trivial to make this function tail recursive.

The times for this were very interesting. This function (tail recursive version) took 50% more than the original, and the imperative solution took approx 3 times as long again! Yes - the original functional solution is the fastest, this is the next fastest, and the imperative list comprehension was the slowest, by approx 1::1.5::4. Tested on a wide variety of datasets.

送你一个梦 2024-09-25 07:29:08

您可以使用列表理解轻松完成此操作:

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

You can do it easily using list comprehensions:

let GenerateTuples (n:int) =
    [for i in 1..n do for j in 1..n do if i <> j then yield (i,j)]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文