简体   繁体   English

Haskell 在没有显式递归的情况下生成具有适当性的随机数

[英]Haskell generate random numbers with a propriety without explicit recursion

Here I have a function to generate a stream of random numbers between 0 and 999.这里我有一个函数来生成 0 到 999 之间的随机数流。

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

I would like to select all numbers from the stream defined above and each elem(i) and elem(i + 1) must respect a propriety.我想从上面定义的流中选择所有数字,并且每个elem(i)elem(i + 1)必须尊重一个特性。 For example their gcd have to be one.例如他们的 gcd 必须是一个。 All I can think is a fold function with because I can start with and accumulator which contains the number 1 (let's assume 1 will be the first element I want to show) then I check the propriety in fold's function and if it is respected i add the element to the accumulator, but the problem is the program blocks because of stackoverflow I think.我能想到的只是一个折叠函数,因为我可以从包含数字 1 的累加器开始(假设 1 将是我想要显示的第一个元素)然后我检查折叠函数的适当性,如果它受到尊重,我添加累加器的元素,但问题是程序块,因为我认为是 stackoverflow。

Here is the function:这是函数:

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

Note: I don't want to use explicit recursion.注意:我不想使用显式递归。

A right fold would probably fit better, something like:正确的折叠可能更适合,例如:

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

then然后

\> 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]

Doing so you may build the list using : instead of ++ which may cause quadratic performance cost, and you may bypass the call to last .这样做您可以使用:而不是++来构建列表,这可能会导致二次性能成本,并且您可以绕过对last的调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM