-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArray.purs
49 lines (39 loc) · 1.37 KB
/
Array.purs
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 Epicbot.Random.Array
( shuffle
, takeRandom
) where
import Prelude
import Control.Monad.Rec.Class (class MonadRec)
import Data.Array ((..))
import Data.Array as Array
import Data.Map (Map)
import Data.Map as Map
import Data.Maybe (Maybe, fromMaybe)
import Data.Tuple (Tuple(..))
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Random as Random
takeRandom :: forall a m. MonadEffect m => MonadRec m => Int -> Array a -> m (Array a)
takeRandom n xs = Array.take n <$> shuffle xs
shuffle :: forall a m. MonadEffect m => MonadRec m => Array a -> m (Array a)
shuffle xs = mapToArray <$> Array.foldRecM swap (arrayToMap xs) (0..upperBound)
where
upperBound :: Int
upperBound = Array.length xs - 1
mapToArray :: Map Int a -> Array a
mapToArray m =
Array.mapMaybe (flip Map.lookup m)
<<< Array.sort
<<< Array.fromFoldable
<<< Map.keys
$ m
arrayToMap :: Array a -> Map Int a
arrayToMap = Map.fromFoldable <<< Array.mapWithIndex Tuple
swap :: Map Int a -> Int -> m (Map Int a)
swap map i = do
j <- liftEffect $ Random.randomInt i upperBound
pure <<< fromMaybe map <<< swapKeys i j $ map
swapKeys :: Int -> Int -> Map Int a -> Maybe (Map Int a)
swapKeys i j map = do
iVal <- Map.lookup i map
jVal <- Map.lookup j map
pure <<< Map.insert i jVal <<< Map.insert j iVal $ map