【问题标题】:Haskell generate random numbers with a propriety without explicit recursionHaskell 在没有显式递归的情况下生成具有适当性的随机数
【发布时间】:2016-04-21 05:22:26
【问题描述】:

这里我有一个函数可以生成 0 到 999 之间的随机数流。

randomHelp :: RandomGen g => g -> [Int]
randomHelp g = zipWith (mod) (map fst $ iterate (next . snd) $ next $ snd $ split g) $ repeat 1000

我想从上面定义的流中选择所有数字,并且每个 elem(i)elem(i + 1) 都必须尊重适当性。例如,他们的 gcd 必须是一个。我能想到的只是一个折叠函数,因为我可以从包含数字 1 的累加器开始(假设 1 将是我要显示的第一个元素)然后我检查折叠函数的适当性,如果它受到尊重,我添加累加器的元素,但问题是我认为由于stackoverflow而导致程序阻塞。

函数如下:

randomFunc :: RandomGen g => g -> [Int]
randomFunc g = foldl (\acc x -> if (gcd x (last acc) == 1) then acc ++ [x] else acc) [1] (randomHelp g)

注意:我不想使用显式递归。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    正确的折叠可能更合适,例如:

    import System.Random (RandomGen, randomRs, mkStdGen)
    
    randomFunc :: RandomGen g => g -> [Int]
    randomFunc g = foldr go (const []) (randomRs (1, 20) g) 1
        where go x f lst = if gcd x lst == 1 then x: f x else f lst
    

    然后

    \> take 20 . randomFunc $ mkStdGen 1
    [16,7,6,19,8,15,16,1,9,2,15,17,14,3,11,17,15,8,1,5]
    

    这样做您可以使用: 而不是++ 来构建列表,这可能会导致二次性能成本,并且您可以绕过对last 的调用。

    【讨论】:

    • 我不太明白这是怎么回事?你能解释一下吗?
    • @zaig 这是foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b 的应用程序,其中b 本身是一个函数,如c -> d,因此签名将是(a -> (c -> d) -> c -> d) -> (c -> d) -> t a -> c -> d。如果您遵循签名应该是有意义的它是如何工作的
    • 我还是不明白函数f是谁?按照顺序,我会说在调用 go 时它将是 randomRs,但 randomRs 需要一个生成器,而 lstx 不是生成器。我还是有点困惑。我错过了什么?
    • @zaig (randomRs (1, 20) g) 是一个无限列表,它已经传入了生成器g。你可以用任意列表替换(randomRs (1, 20) g),比如[2, 3, 6, 8, 5],看看它是如何工作的
    • 如果你能用[2, 3, 6]列表逐步解释代码,我将不胜感激。当调用go 函数时,我不知道f 是谁。还有go 采用的参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    相关资源
    最近更新 更多