-- Copyright 2013 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

module Util.Random where
import qualified System.Random.Shuffle as Shuffle

import qualified Util.Num as Num


-- | Shuffle a list by a list of random integers.  The random list must be
-- at least as long as the list to shuffle.
shuffle :: [a] -> [Int] -> [a]
shuffle :: forall a. [a] -> [Int] -> [a]
shuffle [a]
xs = forall a. [a] -> [Int] -> [a]
Shuffle.shuffle [a]
xs forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [Int]
mangle
    where
    -- Shuffle has a really complicated precondition and crashes if it doesn't
    -- get it.
    mangle :: [Int] -> [Int]
mangle [Int]
rs = [forall a. Real a => a -> a -> a -> a
Num.restrict Int
0 (Int
lenforall a. Num a => a -> a -> a
+Int
1forall a. Num a => a -> a -> a
-Int
i) Int
v | (Int
i, Int
v) <- forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] (forall a. Int -> [a] -> [a]
take Int
len [Int]
rs)]
    len :: Int
len = forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs forall a. Num a => a -> a -> a
- Int
1