乱数の扱いは難しい

重複無し乱数です。乱数に大苦戦。

与えられたリストからランダムに一つ選んで、選んだもの以外のリストからさらにランダムに一つ選んで……、というやり方です。

import System.Random

main = bingo(10) >>= print

bingo :: Int -> IO [Int]
bingo n = do g <- getStdGen
             return $ randomGet g [1..n]

randomGet :: (Eq a) => StdGen -> [a] -> [a]
randomGet _ [] = []
randomGet g xs = let (n, gen) = rnd g (0, (length xs) - 1)
                     a = xs !! n
                     ys = filter (/= a) xs
                     zs = randomGet gen ys
                 in (a : zs)

rnd :: StdGen -> (Int, Int) -> (Int, StdGen)
rnd g range = randomR range g

投稿されていたプログラムを見るとrandomRIOというのを使っていたので、私も使ってみました。

import System.Random

main = bingo(10) >>= print

bingo :: Int -> IO [Int]
bingo n = randomGet [1..n]

randomGet :: (Eq a) => [a] -> IO [a]
randomGet [] = return []
randomGet xs = do n <- randomRIO (0, (length xs) - 1)
                  let a = xs !! n
                  let ys = filter (/= a) xs
                  zs <- randomGet ys
                  return (a : zs)

リストユーティリティを見るとdeleteなんていうのがあるので使ってみました。

import Data.List
import System.Random

main = bingo(10) >>= print

bingo :: Int -> IO [Int]
bingo n = randomGet [1..n]

randomGet :: (Eq a) => [a] -> IO [a]
randomGet [] = return []
randomGet xs = do n <- randomRIO (0, (length xs) - 1)
                  let a = xs !! n
                  ys <- randomGet(delete a xs)
                  return (a : ys)