{-# Language PatternSynonyms, ViewPatterns #-}
{-# Options_GHC -Wno-name-shadowing #-}
module Advent.Queue (Queue(Empty, (:<|)), (|>), singleton, fromList, snoc, pop, appendList) where
import Data.Foldable (Foldable(..))
import Data.Monoid (Dual(..))
import Data.Coerce (coerce)
data Queue a = Queue [a] [a] !Int
{-# COMPLETE (:<|), Empty #-}
pattern Empty :: Queue a
pattern $bEmpty :: forall a. Queue a
$mEmpty :: forall {r} {a}. Queue a -> (Void# -> r) -> (Void# -> r) -> r
Empty <- Queue [] _ _
where
Empty = [a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
Queue [] [] Int
0
pattern (:<|) :: a -> Queue a -> Queue a
pattern x $m:<| :: forall {r} {a}. Queue a -> (a -> Queue a -> r) -> (Void# -> r) -> r
:<| xs <- (pop -> Just (x, xs))
(|>) :: Queue a -> a -> Queue a
Queue a
q |> :: forall a. Queue a -> a -> Queue a
|> a
x = a -> Queue a -> Queue a
forall a. a -> Queue a -> Queue a
snoc a
x Queue a
q
{-# INLINE (|>) #-}
instance Foldable Queue where
null :: forall a. Queue a -> Bool
null (Queue [a]
l [a]
_ Int
_) = [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
l
length :: forall a. Queue a -> Int
length (Queue [a]
l [a]
r Int
_) = [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
r
elem :: forall a. Eq a => a -> Queue a -> Bool
elem a
x (Queue [a]
l [a]
r Int
_) = a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
x [a]
l Bool -> Bool -> Bool
|| a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
x [a]
r
sum :: forall a. Num a => Queue a -> a
sum (Queue [a]
l [a]
r Int
_) = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [a]
l a -> a -> a
forall a. Num a => a -> a -> a
+ [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [a]
r
foldMap :: forall m a. Monoid m => (a -> m) -> Queue a -> m
foldMap a -> m
_ (Queue [] [a]
_ Int
_) = m
forall a. Monoid a => a
mempty
foldMap a -> m
f (Queue (a
x:[a]
l) [a]
r Int
0) = a -> m
f a
x m -> m -> m
forall a. Semigroup a => a -> a -> a
<> [a] -> [a] -> m
rot [a]
l [a]
r
where
rot :: [a] -> [a] -> m
rot [] (a
y:[a]
_ ) = a -> m
f a
y
rot (a
x:[a]
xs) (a
y:[a]
ys) = a -> m
f a
x m -> m -> m
forall a. Semigroup a => a -> a -> a
<> [a] -> [a] -> m
rot [a]
xs [a]
ys m -> m -> m
forall a. Semigroup a => a -> a -> a
<> a -> m
f a
y
foldMap a -> m
f (Queue (a
x:[a]
l) [a]
r Int
i) = a -> m
f a
x m -> m -> m
forall a. Semigroup a => a -> a -> a
<> (a -> m) -> Queue a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f ([a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
Queue [a]
l [a]
r (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
instance Show a => Show (Queue a) where
showsPrec :: Int -> Queue a -> ShowS
showsPrec Int
p Queue a
q
= Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
11)
(ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"fromList "
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> ShowS
forall a. Show a => a -> ShowS
shows (Queue a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Queue a
q)
instance Read a => Read (Queue a) where
readsPrec :: Int -> ReadS (Queue a)
readsPrec Int
prec
= Bool -> ReadS (Queue a) -> ReadS (Queue a)
forall a. Bool -> ReadS a -> ReadS a
readParen (Int
prec Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
11) (ReadS (Queue a) -> ReadS (Queue a))
-> ReadS (Queue a) -> ReadS (Queue a)
forall a b. (a -> b) -> a -> b
$ \String
str ->
do (String
"fromList", String
str) <- ReadS String
lex String
str
([a]
xs, String
str) <- ReadS [a]
forall a. Read a => ReadS a
reads String
str
(Queue a, String) -> [(Queue a, String)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> Queue a
forall a. [a] -> Queue a
fromList [a]
xs, String
str)
singleton :: a -> Queue a
singleton :: forall a. a -> Queue a
singleton a
x = [a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
Queue [a
x] [] Int
1
fromList :: [a] -> Queue a
fromList :: forall a. [a] -> Queue a
fromList [a]
xs = [a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
Queue [a]
xs [] ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs)
appendList :: [a] -> Queue a -> Queue a
appendList :: forall a. [a] -> Queue a -> Queue a
appendList [a]
xs Queue a
q = (Queue a -> a -> Queue a) -> Queue a -> [a] -> Queue a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Queue a -> a -> Queue a
forall a. Queue a -> a -> Queue a
(|>) Queue a
q [a]
xs
pop :: Queue a -> Maybe (a, Queue a)
pop :: forall a. Queue a -> Maybe (a, Queue a)
pop (Queue (a
x:[a]
f) [a]
r Int
s) = (a, Queue a) -> Maybe (a, Queue a)
forall a. a -> Maybe a
Just (a
x, [a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
exec [a]
f [a]
r Int
s)
pop Queue a
_ = Maybe (a, Queue a)
forall a. Maybe a
Nothing
snoc :: a -> Queue a -> Queue a
snoc :: forall a. a -> Queue a -> Queue a
snoc a
x (Queue [a]
f [a]
r Int
s) = [a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
exec [a]
f (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
r) Int
s
exec :: [a] -> [a] -> Int -> Queue a
exec :: forall a. [a] -> [a] -> Int -> Queue a
exec [a]
f [a]
r Int
0 = [a] -> Queue a
forall a. [a] -> Queue a
fromList ([a] -> [a] -> [a] -> [a]
forall {a}. [a] -> [a] -> [a] -> [a]
rotate [a]
f [a]
r [])
exec [a]
f [a]
r Int
i = [a] -> [a] -> Int -> Queue a
forall a. [a] -> [a] -> Int -> Queue a
Queue [a]
f [a]
r (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
rotate :: [a] -> [a] -> [a] -> [a]
rotate [] (a
y:[a]
_ ) [a]
a = a
y a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
a
rotate (a
x:[a]
xs) (a
y:[a]
ys) [a]
a = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a] -> [a] -> [a]
rotate [a]
xs [a]
ys (a
ya -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
a)
rotate [a]
_ [a]
_ [a]
_ = String -> [a]
forall a. HasCallStack => String -> a
error String
"Advent.Queue.rotate: panic"