RosettaCodeData/Task/Knuth-shuffle/Haskell/knuth-shuffle-2.hs
2019-09-12 10:33:56 -07:00

22 lines
664 B
Haskell

import System.Random (randomRIO)
import Data.Bool (bool)
knuthShuffle :: [a] -> IO [a]
knuthShuffle xs = (foldr swapped xs . zip [1 ..]) <$> randoms (length xs)
swapped :: (Int, Int) -> [a] -> [a]
swapped (i, j) xs =
let go (a, b)
| a == b = xs
| otherwise =
let (m, n) = bool (b, a) (a, b) (b > a)
(l, hi:t) = splitAt m xs
(ys, lo:zs) = splitAt (pred (n - m)) t
in concat [l, lo : ys, hi : zs]
in bool xs (go (i, j)) $ ((&&) . (i <) <*> (j <)) $ length xs
randoms :: Int -> IO [Int]
randoms x = mapM (randomRIO . (,) 0) [1 .. pred x]
main :: IO ()
main = knuthShuffle ['a' .. 'k'] >>= print