summaryrefslogtreecommitdiff
path: root/minmax-psq/src/Data/MinMaxPSQ.hs
diff options
context:
space:
mode:
Diffstat (limited to 'minmax-psq/src/Data/MinMaxPSQ.hs')
-rw-r--r--minmax-psq/src/Data/MinMaxPSQ.hs112
1 files changed, 112 insertions, 0 deletions
diff --git a/minmax-psq/src/Data/MinMaxPSQ.hs b/minmax-psq/src/Data/MinMaxPSQ.hs
new file mode 100644
index 00000000..e7d7c760
--- /dev/null
+++ b/minmax-psq/src/Data/MinMaxPSQ.hs
@@ -0,0 +1,112 @@
1{-# LANGUAGE BangPatterns, PatternSynonyms #-}
2module Data.MinMaxPSQ
3 ( module Data.MinMaxPSQ
4 , Binding'
5 , pattern Binding
6 ) where
7
8import Data.Ord
9import qualified Data.Wrapper.PSQ as PSQ
10 ;import Data.Wrapper.PSQ as PSQ hiding (insert, insert', null, size)
11import Prelude hiding (null, take)
12
13data MinMaxPSQ' k p v = MinMaxPSQ !Int !(PSQ' k p v) !(PSQ' k (Down p) v)
14type MinMaxPSQ k p = MinMaxPSQ' k p ()
15
16empty :: MinMaxPSQ' k p v
17empty = MinMaxPSQ 0 PSQ.empty PSQ.empty
18
19singleton' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v
20singleton' k v p = MinMaxPSQ 1 (PSQ.singleton' k v p) (PSQ.singleton' k v (Down p))
21
22null :: MinMaxPSQ' k p v -> Bool
23null (MinMaxPSQ sz _ _) = sz==0
24{-# INLINE null #-}
25
26size :: MinMaxPSQ' k p v -> Int
27size (MinMaxPSQ sz _ _) = sz
28{-# INLINE size #-}
29
30toList :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> [Binding' k p v]
31toList (MinMaxPSQ _ nq xq) = PSQ.toList nq
32
33fromList :: (PSQKey k, Ord p) => [Binding' k p v] -> MinMaxPSQ' k p v
34fromList kps = let nq = PSQ.fromList kps
35 xq = PSQ.fromList $ map (\(Binding k v p) -> Binding k v (Down p)) kps
36 in MinMaxPSQ (PSQ.size nq) nq xq
37
38findMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v)
39findMin (MinMaxPSQ _ nq xq) = PSQ.findMin nq
40
41findMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v)
42findMax (MinMaxPSQ _ nq xq) = fmap (\(Binding k v (Down p)) -> Binding k v p) $ PSQ.findMin xq
43
44insert :: (PSQKey k, Ord p) => k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p
45insert k p (MinMaxPSQ sz nq xq) = case PSQ.insertView k p () nq of
46 (Just _ ,nq') -> MinMaxPSQ sz nq' (PSQ.insert k (Down p) xq)
47 (Nothing,nq') -> MinMaxPSQ (sz+1) nq' (PSQ.insert k (Down p) xq)
48
49insert' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
50insert' k v p (MinMaxPSQ sz nq xq) = case PSQ.insertView k p v nq of
51 (Just _ ,nq') -> MinMaxPSQ sz nq' (PSQ.insert' k v (Down p) xq)
52 (Nothing,nq') -> MinMaxPSQ (sz+1) nq' (PSQ.insert' k v (Down p) xq)
53
54delete :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
55delete k q@(MinMaxPSQ sz nq xq) = case PSQ.deleteView k nq of
56 Just (_,_,nq') -> MinMaxPSQ (sz - 1) nq' (PSQ.delete k xq)
57 Nothing -> q
58
59deleteMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v
60deleteMin q@(MinMaxPSQ sz nq xq) = case PSQ.minView nq of
61 Just (Binding k _ _, nq') -> MinMaxPSQ (sz - 1) nq' (PSQ.delete k xq)
62 Nothing -> q
63
64deleteMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v
65deleteMax q@(MinMaxPSQ sz nq xq) = case PSQ.minView xq of
66 Just (Binding k _ _, xq') -> MinMaxPSQ (sz - 1) (PSQ.delete k nq) xq'
67 Nothing -> q
68
69minView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v)
70minView (MinMaxPSQ sz nq xq) = fmap (\(Binding k v p, nq') -> (Binding k v p, MinMaxPSQ (sz-1) nq' (PSQ.delete k xq)))
71 $ PSQ.minView nq
72
73maxView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v)
74maxView (MinMaxPSQ sz nq xq) = fmap (\(Binding k v (Down p), xq') -> (Binding k v p, MinMaxPSQ (sz-1) (PSQ.delete k nq) xq'))
75 $ PSQ.minView xq
76
77-- | Maintains a bounded 'MinMaxPSQ' by deleting the maximum element if the
78-- insertion would cause the queue to have too many elements.
79insertTake :: (PSQKey k, Ord p) => Int -> k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p
80insertTake n k p q
81 | size q < n = insert k p q
82 | size q == n = insert k p $ deleteMax q
83 | otherwise = take n $ insert k p q
84
85-- | Maintains a bounded 'MinMaxPSQ\'' by deleting the maximum element if the
86-- insertion would cause the queue to have too many elements.
87insertTake' :: (PSQKey k, Ord p) => Int -> k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
88insertTake' n k v p q
89 | size q < n = insert' k v p q
90 | size q == n = insert' k v p $ deleteMax q
91 | otherwise = take n $ insert' k v p q
92
93
94-- | Truncate the 'MinMaxPSQ' to the given number of lowest priority elements.
95take :: (PSQKey k, Ord p) => Int -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
96take !n !q | (size q <= n) = q
97 | null q = q
98 | otherwise = take n $ deleteMax q
99
100-- | Like 'take', except it provides a list deleted bindings.
101takeView :: (PSQKey k, Ord p) => Int -> MinMaxPSQ' k p v -> ( [Binding' k p v], MinMaxPSQ' k p v )
102takeView !n !q | (size q <= n) = ([], q)
103 | null q = ([], q)
104 | otherwise = let Just (x,q') = maxView q
105 (xs,q'') = takeView n q'
106 ys = x:xs
107 in (ys, ys `seq` q'')
108
109
110
111lookup' :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> Maybe (p, v)
112lookup' k (MinMaxPSQ _ q _) = PSQ.lookup k q