[Haskell-cafe] Strange random choice algorithm

Daniel Fischer daniel.is.fischer at web.de
Sat Jan 30 15:38:34 EST 2010


Am Samstag 30 Januar 2010 20:59:08 schrieb michael rice:
> I'm not sure where I got this PICK function from, and don't understand
> why it's written as it is, so I wanted to test it for randomness. It
> seems random enough. But if I understand the algorithm correctly,
> instead of selecting one of the elements from the list, it eliminates
> all the elements but one and that's the value it returns.

Yep.

> Seems like a
> roundabout way of doing it. Comments?

Indeed.

>
> Also, is there a more direct way of printing an array?

Sure,

printing immutable arrays:

print arr ~> array (lo,hi) [(lo,arr!lo), ... , (hi,arr!hi)]
print (assocs arr) ~> [(lo,arr!lo), ... , (hi,arr!hi)]
print (elems arr) ~> [(arr!lo), ... , (arr!hi)]

printing IO[U]Arrays:

do immArr <- freeze arr
   print (immArr :: [U]Array ix el)

do ass <- getAssocs arr
   print ass

(getAssocs arr >>= print)

do els <- getElems arr
   print els

(getElems arr >>= print)

or, to get output like below:

getElems arr >>= mapM_ print

Printing ST[U]Arrays would need an unsafeIOToST, but reasonably, you 
wouldn't want to print them before you've left ST.

>
> Output below.
>
> Michael
>
> =================
>
> import System.Random
> import Data.Array.IO
>
> pick :: [a] -> IO a
> pick []     = undefined
> pick [x]    = do return x
> pick (x:xs) = pick' x xs (2 :: Int)
>
> pick' :: (Num p, Random p) => t -> [t] -> p -> IO t
> pick' curr []          _    = do return curr
> pick' curr (next:rest) prob
>   = do r <- getStdRandom (randomR (1,prob))
>        let curr' = if r == 1 then next else curr
>        pick' curr' rest (prob+1)
>
> main = do arr <- newArray (1,9) 0 :: IO (IOArray Int Int)
>           doLoop arr [1,2,3,4,5,6,7,8,9] 0
>          
> doLoop arr z k = do p <- pick z
>                     a <- readArray arr p
>                     writeArray arr p (a+1)
>                     if k > 10000
>                       then do
>                         v <- readArray arr 1
>                         print v
>                         v <- readArray arr 2
>                         print v
>                         v <- readArray arr 3
>                         print v
>                         v <- readArray arr 4
>                         print v
>                         v <- readArray arr 5
>                         print v
>                         v <- readArray arr 6
>                         print v
>                         v <- readArray arr 7
>                         print v
>                         v <- readArray arr 8
>                         print v
>                         v <- readArray arr 9
>                         print v
>                       else do
>                         doLoop arr z (k+1)
>
> ===============
>
> [michael at localhost ~]$ runhaskell array1.hs
> 1110
> 1117
> 1080
> 1169
> 1112
> 1119
> 1137
> 1084
> 1074
> [michael at localhost ~]$



More information about the Haskell-Cafe mailing list