{- |
Description: Rotate a list
Copyright: Copyright (C) 2021 Yoo Chung
License: GPL-3.0-or-later
Maintainer: dev@chungyc.org

Some solutions to "Problems.P19" of Ninety-Nine Haskell "Problems".
-}
module Solutions.P19 (rotate) where

-- | Rotate a list @n@ places to the left.
rotate :: [a] -> Int -> [a]
rotate :: forall a. [a] -> Int -> [a]
rotate [] Int
_ = []
rotate [a]
xs Int
n = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
shift [a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
shift [a]
xs
  where m :: Int
m = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs
        modShift :: Int
modShift = Int
n Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
m
        shift :: Int
shift
          | Int
modShift Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
modShift
          | Bool
otherwise    = Int
modShift