Difference between revisions of "99 questions/Solutions/24"
< 99 questions | Solutions
Jump to navigation
Jump to search
Amackillop (talk | contribs) (Provided solutions using nub may not terminate.) |
|||
(3 intermediate revisions by 3 users not shown) | |||
Line 32: | Line 32: | ||
(Note that this doesn't really solve the problem, since it doesn't generate ''distinct'' numbers). |
(Note that this doesn't really solve the problem, since it doesn't generate ''distinct'' numbers). |
||
− | Using nub: |
+ | Using nub from Data.List: |
<haskell> |
<haskell> |
||
diff_select :: Int -> Int -> StdGen -> [Int] |
diff_select :: Int -> Int -> StdGen -> [Int] |
||
diff_select n m = take n . nub . randomRs (1, m) |
diff_select n m = take n . nub . randomRs (1, m) |
||
</haskell> |
</haskell> |
||
+ | |||
+ | Or without giving StdGen as argument and returning IO [Int]: |
||
+ | <haskell> |
||
+ | import System.Random |
||
+ | import Data.List |
||
+ | import Control.Applicative |
||
+ | |||
+ | diff_select :: Int -> Int -> IO [Int] |
||
+ | diff_select n m = take n . nub . randomRs (1, m) <$> getStdGen |
||
+ | </haskell> |
||
+ | |||
+ | Note: With the above solutions using nub, the function will not terminate if m < n. I suggest adding a guard to protect against this. |
||
+ | [[Category:Programming exercise spoilers]] |
Latest revision as of 00:09, 7 April 2019
Lotto: Draw N different random numbers from the set 1..M.
import System.Random
diff_select :: Int -> Int -> IO [Int]
diff_select n to = diff_select' n [1..to]
diff_select' 0 _ = return []
diff_select' _ [] = error "too few elements to choose from"
diff_select' n xs = do r <- randomRIO (0,(length xs)-1)
let remaining = take r xs ++ drop (r+1) xs
rest <- diff_select' (n-1) remaining
return ((xs!!r) : rest)
The random numbers have to be distinct!
In order to use randomRIO here, we need import module System.Random.
As can be seen, having implemented problem 23, rnd_select, the solution is trivial.
diff_select n to = rnd_select [1..to] n
Alternative solution:
diffSelect :: Int -> Int -> IO [Int]
diffSelect n m = do
gen <- getStdGen
return . take n $ randomRs (1, m) gen
(Note that this doesn't really solve the problem, since it doesn't generate distinct numbers).
Using nub from Data.List:
diff_select :: Int -> Int -> StdGen -> [Int]
diff_select n m = take n . nub . randomRs (1, m)
Or without giving StdGen as argument and returning IO [Int]:
import System.Random
import Data.List
import Control.Applicative
diff_select :: Int -> Int -> IO [Int]
diff_select n m = take n . nub . randomRs (1, m) <$> getStdGen
Note: With the above solutions using nub, the function will not terminate if m < n. I suggest adding a guard to protect against this.