module ALife.Creatur.Util
(
ilogBase,
isPowerOf,
isqrt,
perfectSquare,
cropRect,
cropSquare,
replaceElement,
reverseLookup,
rotate,
safeReplaceElement,
shuffle,
boolsToBits,
showBin,
stateMap,
fromEither,
catEithers,
modifyLift,
getLift
) where
import Control.Monad (forM_, liftM)
import Control.Monad.Random (Rand, RandomGen, getRandomRs)
import Control.Monad.State (StateT(..), get, lift, put)
import Data.Array.ST (runSTArray)
import Data.Char (intToDigit)
import Data.List.Split (chunksOf)
import GHC.Arr (elems, listArray, readSTArray, thawSTArray, writeSTArray)
import Numeric (showIntAtBase)
shuffle :: RandomGen g => [a] -> Rand g [a]
shuffle :: [a] -> Rand g [a]
shuffle [a]
xs = do
let l :: Int
l = [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs
[Int]
rands <- Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take Int
l ([Int] -> [Int])
-> RandT g Identity [Int] -> RandT g Identity [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` (Int, Int) -> RandT g Identity [Int]
forall (m :: * -> *) a.
(MonadRandom m, Random a) =>
(a, a) -> m [a]
getRandomRs (Int
0, Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
let ar :: Array Int a
ar = (forall s. ST s (STArray s Int a)) -> Array Int a
forall i e. (forall s. ST s (STArray s i e)) -> Array i e
runSTArray ((forall s. ST s (STArray s Int a)) -> Array Int a)
-> (forall s. ST s (STArray s Int a)) -> Array Int a
forall a b. (a -> b) -> a -> b
$ do
STArray s Int a
ar' <- Array Int a -> ST s (STArray s Int a)
forall i e s. Array i e -> ST s (STArray s i e)
thawSTArray (Array Int a -> ST s (STArray s Int a))
-> Array Int a -> ST s (STArray s Int a)
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> [a] -> Array Int a
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
xs
[(Int, Int)] -> ((Int, Int) -> ST s ()) -> ST s ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..(Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)] [Int]
rands) (((Int, Int) -> ST s ()) -> ST s ())
-> ((Int, Int) -> ST s ()) -> ST s ()
forall a b. (a -> b) -> a -> b
$ \(Int
i, Int
j) -> do
a
vi <- STArray s Int a -> Int -> ST s a
forall i s e. Ix i => STArray s i e -> i -> ST s e
readSTArray STArray s Int a
ar' Int
i
a
vj <- STArray s Int a -> Int -> ST s a
forall i s e. Ix i => STArray s i e -> i -> ST s e
readSTArray STArray s Int a
ar' Int
j
STArray s Int a -> Int -> a -> ST s ()
forall i s e. Ix i => STArray s i e -> i -> e -> ST s ()
writeSTArray STArray s Int a
ar' Int
j a
vi
STArray s Int a -> Int -> a -> ST s ()
forall i s e. Ix i => STArray s i e -> i -> e -> ST s ()
writeSTArray STArray s Int a
ar' Int
i a
vj
STArray s Int a -> ST s (STArray s Int a)
forall (m :: * -> *) a. Monad m => a -> m a
return STArray s Int a
ar'
[a] -> Rand g [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Array Int a -> [a]
forall i e. Array i e -> [e]
elems Array Int a
ar)
safeReplaceElement :: [a] -> Int -> a -> [a]
safeReplaceElement :: [a] -> Int -> a -> [a]
safeReplaceElement [a]
xs Int
i a
x =
if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs
then [a] -> Int -> a -> [a]
forall a. [a] -> Int -> a -> [a]
replaceElement [a]
xs Int
i a
x
else [a]
xs
replaceElement :: [a] -> Int -> a -> [a]
replaceElement :: [a] -> Int -> a -> [a]
replaceElement [a]
xs Int
i a
x =
if Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs then [a]
fore [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
aft) else [a]
xs
where fore :: [a]
fore = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
i [a]
xs
aft :: [a]
aft = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [a]
xs
cropSquare :: Int -> [a] -> [a]
cropSquare :: Int -> [a] -> [a]
cropSquare Int
n [a]
xs | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = []
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
m =
(Int, Int) -> (Int, Int) -> [a] -> Int -> [a]
forall a. (Int, Int) -> (Int, Int) -> [a] -> Int -> [a]
cropRect (Int
margin, Int
margin) (Int
marginInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1, Int
marginInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
xs Int
m
| Bool
otherwise = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
m) [a]
xs
where m :: Int
m = (Int -> Int
forall a b. (Integral a, Integral b) => a -> b
isqrt (Int -> Int) -> ([a] -> Int) -> [a] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) [a]
xs
margin :: Int
margin = (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2
cropRect :: (Int, Int) -> (Int, Int) -> [a] -> Int -> [a]
cropRect :: (Int, Int) -> (Int, Int) -> [a] -> Int -> [a]
cropRect (Int
a,Int
b) (Int
c, Int
d) [a]
xs Int
k = ([a] -> [a]) -> [[a]] -> [a]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [a] -> [a]
forall a. [a] -> [a]
f [[a]]
selectedRows
where rows :: [[a]]
rows = if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 then [] else Int -> [a] -> [[a]]
forall e. Int -> [e] -> [[e]]
chunksOf Int
k [a]
xs
selectedRows :: [[a]]
selectedRows = Int -> Int -> [[a]] -> [[a]]
forall a. Int -> Int -> [a] -> [a]
safeSlice Int
a Int
c [[a]]
rows
f :: [a] -> [a]
f = Int -> Int -> [a] -> [a]
forall a. Int -> Int -> [a] -> [a]
safeSlice Int
b Int
d
safeSlice :: Int -> Int -> [a] -> [a]
safeSlice :: Int -> Int -> [a] -> [a]
safeSlice Int
a Int
b = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
a ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take (Int
bInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
isqrt :: (Integral a, Integral b) => a -> b
isqrt :: a -> b
isqrt a
n = (Float -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (Float -> b) -> (Float -> Float) -> Float -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Float
forall a. Floating a => a -> a
sqrt) Float
n'
where n' :: Float
n' = a -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n :: Float
ilogBase :: (Integral a, Integral b, Integral c) => a -> b -> c
ilogBase :: a -> b -> c
ilogBase a
n b
m = (Float -> c
forall a b. (RealFrac a, Integral b) => a -> b
floor (Float -> c) -> (Float -> Float) -> Float -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Float -> Float
forall a. Floating a => a -> a -> a
logBase Float
n') Float
m'
where n' :: Float
n' = a -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n :: Float
m' :: Float
m' = b -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral b
m :: Float
perfectSquare :: Integral a => a -> Bool
perfectSquare :: a -> Bool
perfectSquare a
n = a
n a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
ma -> a -> a
forall a. Num a => a -> a -> a
*a
m
where m :: a
m = a -> a
forall a b. (Integral a, Integral b) => a -> b
isqrt a
n
isPowerOf :: Integral a => a -> a -> Bool
isPowerOf :: a -> a -> Bool
isPowerOf a
n a
m = a
n a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
ma -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^Int
k
where k :: Int
k = a -> a -> Int
forall a b c. (Integral a, Integral b, Integral c) => a -> b -> c
ilogBase a
m a
n :: Int
reverseLookup :: (Eq b) => b -> [(a,b)] -> Maybe a
reverseLookup :: b -> [(a, b)] -> Maybe a
reverseLookup b
_ [] = Maybe a
forall a. Maybe a
Nothing
reverseLookup b
value ((a
x,b
y):[(a, b)]
xys)
| b
value b -> b -> Bool
forall a. Eq a => a -> a -> Bool
== b
y = a -> Maybe a
forall a. a -> Maybe a
Just a
x
| Bool
otherwise = b -> [(a, b)] -> Maybe a
forall b a. Eq b => b -> [(a, b)] -> Maybe a
reverseLookup b
value [(a, b)]
xys
stateMap :: Monad m => (s -> t) -> (t -> s) -> StateT s m a -> StateT t m a
stateMap :: (s -> t) -> (t -> s) -> StateT s m a -> StateT t m a
stateMap s -> t
f t -> s
g (StateT s -> m (a, s)
h) = (t -> m (a, t)) -> StateT t m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT ((t -> m (a, t)) -> StateT t m a)
-> (t -> m (a, t)) -> StateT t m a
forall a b. (a -> b) -> a -> b
$ ((a, s) -> (a, t)) -> m (a, s) -> m (a, t)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((s -> t) -> (a, s) -> (a, t)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap s -> t
f) (m (a, s) -> m (a, t)) -> (t -> m (a, s)) -> t -> m (a, t)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> m (a, s)
h (s -> m (a, s)) -> (t -> s) -> t -> m (a, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> s
g
fromEither :: a -> Either e a -> a
fromEither :: a -> Either e a -> a
fromEither a
d Either e a
x = case Either e a
x of {Left e
_ -> a
d; Right a
v -> a
v}
catEithers :: [Either e a] -> [a]
catEithers :: [Either e a] -> [a]
catEithers [Either e a]
ls = [a
x | Right a
x <- [Either e a]
ls]
modifyLift :: Monad m => (s -> m s) -> StateT s m ()
modifyLift :: (s -> m s) -> StateT s m ()
modifyLift s -> m s
f = StateT s m s
forall s (m :: * -> *). MonadState s m => m s
get StateT s m s -> (s -> StateT s m s) -> StateT s m s
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m s -> StateT s m s
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m s -> StateT s m s) -> (s -> m s) -> s -> StateT s m s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> m s
f StateT s m s -> (s -> StateT s m ()) -> StateT s m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= s -> StateT s m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put
getLift :: Monad m => (s -> m ()) -> StateT s m ()
getLift :: (s -> m ()) -> StateT s m ()
getLift s -> m ()
f = StateT s m s
forall s (m :: * -> *). MonadState s m => m s
get StateT s m s -> (s -> StateT s m ()) -> StateT s m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> (s -> m ()) -> s -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> m ()
f StateT s m () -> StateT s m () -> StateT s m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> StateT s m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
rotate :: [a] -> [a]
rotate :: [a] -> [a]
rotate [] = []
rotate (a
x:[a]
xs) = [a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
x]
boolsToBits :: [Bool] -> String
boolsToBits :: [Bool] -> String
boolsToBits = (Bool -> Char) -> [Bool] -> String
forall a b. (a -> b) -> [a] -> [b]
map (\Bool
b -> if Bool
b then Char
'1' else Char
'0')
showBin :: (Integral a,Show a) => a -> ShowS
showBin :: a -> ShowS
showBin = a -> (Int -> Char) -> a -> ShowS
forall a. (Integral a, Show a) => a -> (Int -> Char) -> a -> ShowS
showIntAtBase a
2 Int -> Char
intToDigit