Knuth's algorithm S: Difference between revisions
Content added Content deleted
(add Haskell implementation) |
|||
Line 707: | Line 707: | ||
[30075 29955 30024 30095 30031 30018 29973 29642 30156 30031] |
[30075 29955 30024 30095 30031 30018 29973 29642 30156 30031] |
||
</pre> |
</pre> |
||
=={{header|Haskell}}== |
|||
{{libheader|containers}} |
|||
{{libheader|MonadRandom}} |
|||
{{libheader|random}} |
|||
{{libheader|mtl}} |
|||
<lang haskell> |
|||
import Control.Monad.Random |
|||
import Control.Monad.State |
|||
import qualified Data.Map as M |
|||
import System.Random |
|||
-- s_of_n_creator :: Int -> a -> RandT StdGen (State (Int, [a])) [a] |
|||
s_of_n_creator :: Int -> a -> StateT (Int, [a]) (Rand StdGen) [a] |
|||
s_of_n_creator n v = do |
|||
(i, vs) <- get |
|||
let i' = i + 1 |
|||
if i' <= n |
|||
then do |
|||
let vs' = v : vs |
|||
put (i', vs') |
|||
pure vs' |
|||
else do |
|||
j <- getRandomR (1, i') |
|||
if j > n |
|||
then do |
|||
put (i', vs) |
|||
pure vs |
|||
else do |
|||
k <- getRandomR (0, n - 1) |
|||
let (f, (_ : b)) = splitAt k vs |
|||
vs' = v : f ++ b |
|||
put (i', vs') |
|||
pure vs' |
|||
sample :: Int -> Rand StdGen [Int] |
|||
sample n = |
|||
let s_of_n = s_of_n_creator n |
|||
in snd <$> execStateT (traverse s_of_n [0 .. 9 :: Int]) (0, []) |
|||
incEach :: (Ord a, Num b) => M.Map a b -> [a] -> M.Map a b |
|||
incEach m ks = foldl (\m' k -> M.insertWith (+) k 1 m') m ks |
|||
sampleInc :: Int -> M.Map Int Double -> Rand StdGen (M.Map Int Double) |
|||
sampleInc n m = do |
|||
s <- sample n |
|||
pure $ incEach m s |
|||
main :: IO () |
|||
main = do |
|||
let counts = M.empty :: M.Map Int Double |
|||
n = 100000 |
|||
gen <- getStdGen |
|||
counts <- evalRandIO $ foldM (\c _ -> sampleInc 3 c) M.empty [1 .. n] |
|||
print (fmap (/ n) counts) |
|||
</lang> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |