{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE FlexibleContexts #-}
module Data.Timers.Example
( Map,
gapless,
gapless',
gaplessEq,
countGapless,
countGapless',
nextGapless,
toMathematica,
onlyGapless,
onlyGaplessMathematica,
differences,
differences_,
prop_differences_,
getRuns,
getRunsA,
getRunsB,
getRuns',
getRuns'A,
getRuns'B,
addPosition,
Vec2,
Vec4,
Vec5,
addPosition',
theStream,
printMap,
printMap',
printEveryNOfStream,
printEveryNOfStream',
returnEveryN,
returnEveryN'
) where
import Data.Bits (Bits, (.&.), unsafeShiftR)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Timers (foldlOnce, sideEffectEveryN, printEveryN)
import Control.Monad (liftM2)
import Data.Map.Internal.Debug (showTreeWith)
import Data.List (group)
import Data.Vector.Fixed.Cont (ContVec, mk5)
import Data.Vector.Fixed ()
import qualified Data.Vector.Fixed as FV
gapless :: (Bits t, Num t) => t -> Bool
gapless z = if z == 0
then True
else if 3 .&. z == 0
then gapless $ unsafeShiftR z 2
else gapless' $ unsafeShiftR z 2
gapless' :: (Bits t, Num t) => t -> Bool
gapless' z = if z == 0
then True
else if 3 .&. z == 0
then False
else gapless' $ unsafeShiftR z 2
countGapless :: (Bits a, Enum a, Num a, Num b) => a -> b
countGapless n = sum [ sum [ 1 | gapless i] | i<-[1..n]]
countGapless' :: (Bits a, Enum a, Num a, Num b) => a -> b
countGapless' n = sum [ sum [ 1 | gapless' i] | i<-[1..n]]
gaplessEq :: (Bits a, Num a) => a -> Bool
gaplessEq = liftM2 (==) gapless gapless'
nextGapless :: (Bits a, Num a) => a -> a
nextGapless = until gapless (+1)
onlyGapless :: (Bits t, Num t) => [t] -> [t]
onlyGapless = filter gapless
onlyGaplessMathematica :: (Bits t, Num t, Show t) => [t] -> String
onlyGaplessMathematica = toMathematica . group . differences . onlyGapless
toMathematica :: Show a => [[a]] -> String
toMathematica = (>>= (\x->concat["{",show(head x),",",show(length x),"},"]))
differences :: Num a => [a] -> [a]
differences = zipWith (-) =<< tail
differences_ :: Num a => [a] -> [a]
differences_ = (\x->zipWith(-)(tail x)x)
prop_differences_ :: [Int] -> Bool
prop_differences_ = liftM2 (==) differences differences_
getRuns :: (Num a, Num b, Eq a) => [a] -> [b]
getRuns (1:xs) = getRuns xs
getRuns (_:xs) = getRuns' 1 xs
getRuns _ = error "getRuns: [] is undefined"
getRunsA :: (Num a, Num b, Eq a) => [a] -> [b]
getRunsA [] = []
getRunsA (1:xs) = getRunsA xs
getRunsA ~(_:xs) = getRuns'A 1 xs
getRunsB :: (Num a, Num b, Eq a) => [a] -> [b]
getRunsB (1:xs) = getRunsB xs
getRunsB (_:xs) = getRuns'B 1 xs
getRunsB _ = []
getRuns' :: (Num a, Num b, Eq a) => b -> [a] -> [b]
getRuns' n (1:xs) = n : getRuns xs
getRuns' n (_:xs) = getRuns' (n+1) xs
getRuns' _ _ = error "getRuns' _ [] is undefined"
getRuns'A :: (Num a, Num b, Eq a) => b -> [a] -> [b]
getRuns'A _ [] = []
getRuns'A n (1:xs) = n : getRunsA xs
getRuns'A n ~(_:xs) = getRuns'A (n+1) xs
getRuns'B :: (Num a, Num b, Eq a) => b -> [a] -> [b]
getRuns'B n (1:xs) = n : getRunsB xs
getRuns'B n (_:xs) = getRuns'B (n+1) xs
getRuns'B _ _ = []
addPosition :: (Ord k0, Eq a, Num a) => (a, k0)
-> Map k0 ((a, a, a, a, a), [(a, a, a, a, a)])
-> Map k0 ((a, a, a, a, a), [(a, a, a, a, a)])
addPosition (position, value) posMap = Map.insertWith posValInsert value ((position,0,0,0,0),[]) posMap
type Vec2 = ContVec 2
type Vec4 = ContVec 4
type Vec5 = ContVec 5
addPosition' :: (Ord k0, Eq a, Num a) => a -> k0 -> Map k0 (Vec5 a, [Vec5 a]) -> Map k0 (Vec5 a, [Vec5 a])
addPosition' position value posMap = Map.insertWith posValInsert' value (mk5 position 0 0 0 0, []) posMap
posValInsert :: (Eq a, Num a) => ((a,a,a,a,a),[(a,a,a,a,a)]) ->
((a,a,a,a,a),[(a,a,a,a,a)]) ->
((a,a,a,a,a),[(a,a,a,a,a)])
posValInsert ((pos6,_,_,_,_),_) ((pos1,pos2,pos3,pos4,pos5), pastRuns) = if newRun `elem` pastRuns || 0 `elem` [pos1,pos2,pos3,pos4,pos5,pos6]
then (positions, pastRuns)
else (positions, newRun : pastRuns)
where
newRun = (pos2-pos1,pos3-pos2,pos4-pos3,pos5-pos4,pos6-pos5)
positions = (pos2 ,pos3 ,pos4 ,pos5 ,pos6 )
posValInsert' :: (Eq a, Num a) => (Vec5 a, [Vec5 a]) -> (Vec5 a, [Vec5 a]) -> (Vec5 a, [Vec5 a])
posValInsert' ~((x :: Vec5 a), _) ~(y, zs) = if any (FV.and . FV.zipWith (==) newRun) zs || 0 == sixth || 0 `elem` y
then (positions, zs)
else (positions, newRun : zs)
where
sixth = FV.head x
temp = (FV.tail :: Vec5 a -> Vec4 a) y
positions = FV.snoc sixth temp
newRun = FV.zipWith (-) positions y
printMap :: (Show b, Show c) => (a1, Map b (a, [(c, c, c, c, c)])) -> IO ()
printMap = putStrLn . showTreeWith (\k x -> show (k, snd x)) True False . snd
printMap' :: (Show a0, Show a2) => (a, Map a0 (a1, [Vec5 a2])) -> IO ()
printMap' = (putStrLn . showTreeWith (\k ~(_, xs) -> show (k, FV.toList <$> xs)) True False . snd)
theStream :: (Enum a, Enum b, Num b, Bits b, Num a) => ([(a, b)], Map k v)
theStream = (, Map.empty) . zip [1..] . lock getRuns . differences . lock onlyGapless $ [1..]
where
lock :: ([t] -> [t]) -> [t] -> [t]
lock = id
printEveryNOfStream :: (Eq a, Bits k0, Num k0, Num a, Enum k0, Enum a, Ord k0, Show k0, Show a) =>
Int -> IO ([(a, k0)], Map k0 ((a, a, a, a, a), [(a, a, a, a, a)]))
printEveryNOfStream n = printEveryN (foldlOnce addPosition) n theStream
printEveryNOfStream' :: (Eq a, Bits k0, Num k0, Num a, Enum k0, Enum a, Ord k0, Show (ContVec 5 a), Show k0, Show a) =>
Int -> IO ([(a, k0)], Map k0 (Vec5 a, [Vec5 a]))
printEveryNOfStream' n = printEveryN (foldlOnce (uncurry addPosition')) n theStream
returnEveryN :: (Eq c, Show b, Show c, Ord b, Enum c, Enum b, Num c, Num b, Bits b) => Int
-> IO ([(c, b)], Map b ((c, c, c, c, c), [(c, c, c, c, c)]))
returnEveryN n = sideEffectEveryN printMap (foldlOnce addPosition) n theStream
returnEveryN' :: (Eq a2, Enum a2, Num a2, Bits a1, Enum a1, Num a1, Ord a1, Show a2, Show a1) => Int
-> IO ([(a2, a1)], Map a1 (Vec5 a2, [ContVec 5 a2]))
returnEveryN' n = sideEffectEveryN printMap' (foldlOnce (uncurry addPosition')) n theStream