aboutsummaryrefslogtreecommitdiff
path: root/challenge-073/jeongoon/haskell/JRandomList.hs
blob: 685e05a840c3d14d326521c049a6a5d6bea54d90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module JRandomList
  ( shuffleByPickingAll,
  ) where

import Data.List ( unfoldr, splitAt, tails )
import System.Random ( randomR, Random, StdGen )
import System.Environment (getArgs)


{- Ref:
https://www.schoolofhaskell.com/school/starting-with-haskell/libraries-and-frameworks/randoms
https://hackage.haskell.org/package/containers-0.6.3.1/docs/Data-Sequence.html
https://stackoverflow.com/questions/9834433/convert-data-sequence-to-a-list
https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-List.html
https://en.wikibooks.org/wiki/Haskell/Libraries/Random
https://hackage.haskell.org/package/optparse-generic-1.2.3/docs/Options-Generic.html
-}

descendingRandomR :: (Integral a, Ord a, Random a) =>
                  ((a,   a), StdGen) -> Maybe (a, ((a, a), StdGen))
descendingRandomR ((lo, hi), g) =
  let (rv, g') = randomR (lo, hi) g -- rv: random value from seed(g)
      hi' = hi - 1
  in if lo > hi then Nothing else Just (rv, ((lo, hi'), g'))

indicesToPick :: (Integral a, Random a) =>
  a -> StdGen -> [a] -- input: <highest value> <seed>
indicesToPick = (curry.curry $ unfoldr descendingRandomR) 0 -- 0: first index

popAt :: Int -> [a] -> (Maybe a, [a])
popAt = curry $ (\(le, ri) ->
                    ( if null ri then Nothing else Just (head ri),
                      le ++ tail ri ) ) . (uncurry splitAt)

poping :: ([a], [Int]) -> Maybe (a, ([a], [Int]))
poping ([], _) = Nothing
poping (_, []) = Nothing
poping (ls, idcs) =
  let (e, ls') = popAt (head idcs) ls
      idcs' = tail idcs
  in case e of
      Nothing  -> poping (ls', idcs') -- skip the index which is out of range
      Just e'  -> Just (e', (ls', idcs'))

shuffleByPickingAll :: [a] -> StdGen -> [a]
shuffleByPickingAll ls seed = pick (ls, ( indicesToPick maxIdx seed ))
  where
    pick = unfoldr poping
    maxIdx = ( length ls ) - 1