【问题标题】:Haskell functions to randomly order a list not working properly (Homework) beginnerHaskell 函数随机排序列表无法正常工作(家庭作业)初学者
【发布时间】:2012-04-10 07:14:10
【问题描述】:

几周前才开始使用 Haskell - 我试图通过在随机点 int eh 列表中将列表分成两个来随机打乱 Card 类型的列表(取决于 randomList 函数产生的随机整数数组) 并多次交换这两个部分的顺序,但输出完全不是随机的,解析似乎只发生一次,非常绝望,因为我需要它工作,截止日期是今晚!

randomList :: (Random a) => (a,a) -> Int -> StdGen -> [a]
randomList bnds n = take n . randomRs bnds

randomise :: [Int] -> [Card] -> [Card]
randomise [] p = p
randomise (x : xs) p = do
                    randomise xs ((drop x p) ++ (take x p))

shuffle :: Int -> [Card] -> [Card]
shuffle r p = do
          let g = mkStdGen r
          randomise(randomList (1, (length p)-1) 500 g :: [Int]) p

【问题讨论】:

  • “截止日期”?如果这是家庭作业,您需要将其标记为这样。此外,您能解释一下“完全不随机”是什么意思吗?你如何确定输出的随机性?
  • 您可能对Fisher-Yates shuffle 感兴趣。它可以很容易地适应链表。
  • 这是课程作业,一个随机整数数组被输入randomise,这个数组的长度是500,卡片列表应该被拆分并重新排序500次
  • @RyanConnolly:拆分和重新排序 500 次吗?如果不是,你怎么知道?
  • 尝试用笔和纸完成randomise [3,4,14,20] ['A'..'Z'] 的计算结果(想象type Card = Char 用于此练习)。

标签: list haskell random shuffle


【解决方案1】:

你可以在你的列表上做一个随机数的排列。你可以这样做:

import System.Random
import Data.List

shuffle xs = do
    gen <- getStdGen
    let (permNum,newGen) = randomR (0,fac (length xs) -1) gen
    return $ permutation permNum xs

permutation 在(假定已排序)列表xs 上进行n 排列。但是,在随机化时,xs 不需要排序。

fac 只是阶乘函数的一个实现。

shuffle 生成一个随机数并将那么多排列应用于xs

这与您尝试做的有点不同,但它可以创造奇迹。我假设您不需要明确使用您提出的方法。不过,您必须自己实现 permutationfac

有关permutation 的帮助,您可以查看here。这是解决 Project Euler 问题的描述,但您可以使用相同的过程来进行 n 排列。

编辑:我不知道是否有人再关心了,但我找到了另一种更简单的方法:

import System.Random

randPerm :: StdGen -> [a] -> [a]
randPerm _ []   = []
randPerm gen xs = let (n,newGen) = randomR (0,length xs -1) gen
                      front = xs !! n
                  in  front : randPerm newGen (take n xs ++ drop (n+1) xs)

【讨论】:

  • 最好用提示和线索回答作业问题,而不是提供完整的解决方案。
  • 好吧,我只是觉得没关系,因为截止日期已过。修复。 :)
【解决方案2】:

聚会迟到了,但对建议的解决方案的一个小改进是使用 splitAt 而不是 take & drop:

shuffle :: [a] -> StdGen -> [a]
shuffle []   _   = []
shuffle list generator = let (index,newGenerator) = randomR (0,length list -1) generator
                             (listUntilIndex, element:listAfterIndex) = splitAt index list
                         in  element : shuffle (listUntilIndex ++ listAfterIndex) newGenerator

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2022-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多