Skip to content

Commit

Permalink
slightly optimize deque smart construction
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellwrosen committed Jan 8, 2024
1 parent 3cb01d9 commit cb5defe
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 19 deletions.
23 changes: 15 additions & 8 deletions src/Deque.hs
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,17 @@ pattern Back xs x <-

{-# COMPLETE Empty, Back #-}

-- Deque smart constructor.
makeDeque :: [a] -> Int -> [a] -> Int -> Deque a
makeDeque xs xlen ys ylen
| xlen > (3 * ylen + 1) = Q (List.take xlen1 xs) xlen1 (ys ++ List.reverse (List.drop xlen1 xs)) ylen1
-- Deque smart constructor, to use when it is possible the front list is too long.
makeDeque1 :: [a] -> Int -> [a] -> Int -> Deque a
makeDeque1 xs xlen ys ylen
| xlen > (3 * ylen + 1) = Q (List.take xlen1 xs) xlen1 (ys ++ List.reverse (List.drop xlen1 xs)) (xlen + ylen - xlen1)
| otherwise = Q xs xlen ys ylen
where
xlen1 = (xlen + ylen) `unsafeShiftR` 1

-- Deque smart constructor, to use when it is possible the back list is too long.
makeDeque2 :: [a] -> Int -> [a] -> Int -> Deque a
makeDeque2 xs xlen ys ylen
| ylen > (3 * xlen + 1) = Q (xs ++ List.reverse (List.drop ylen1 ys)) xlen1 (List.take ylen1 ys) ylen1
| otherwise = Q xs xlen ys ylen
where
Expand All @@ -135,26 +142,26 @@ empty =
-- | \(\mathcal{O}(1)^*\). Enqueue an element at the back of a double-ended queue.
enqueue :: a -> Deque a -> Deque a
enqueue y (Q xs xlen ys ylen) =
makeDeque xs xlen (y : ys) (ylen + 1)
makeDeque2 xs xlen (y : ys) (ylen + 1)

-- | \(\mathcal{O}(1)^*\). Enqueue an element at the front of a double-ended queue.
enqueueFront :: a -> Deque a -> Deque a
enqueueFront x (Q xs xlen ys ylen) =
makeDeque (x : xs) (xlen + 1) ys ylen
makeDeque1 (x : xs) (xlen + 1) ys ylen

-- | \(\mathcal{O}(1)\) front, \(\mathcal{O}(1)^*\) rest. Dequeue an element from the front of a double-ended queue.
dequeue :: Deque a -> Maybe (a, Deque a)
dequeue = \case
Q [] _ [] _ -> Nothing
Q [] _ (y : _) _ -> Just (y, empty)
Q (x : xs) xlen ys ylen -> Just (x, makeDeque xs (xlen - 1) ys ylen)
Q (x : xs) xlen ys ylen -> Just (x, makeDeque2 xs (xlen - 1) ys ylen)

-- | \(\mathcal{O}(1)\) back, \(\mathcal{O}(1)^*\) rest. Dequeue an element from of the back of a double-ended queue.
dequeueBack :: Deque a -> Maybe (Deque a, a)
dequeueBack = \case
Q [] _ [] _ -> Nothing
Q (x : _) _ [] _ -> Just (empty, x)
Q xs xlen (y : ys) ylen -> Just (makeDeque xs xlen ys (ylen - 1), y)
Q xs xlen (y : ys) ylen -> Just (makeDeque1 xs xlen ys (ylen - 1), y)

-- | \(\mathcal{O}(1)\). Is a double-ended queue empty?
isEmpty :: Deque a -> Bool
Expand Down
30 changes: 19 additions & 11 deletions src/Deque/RealTime.hs
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,20 @@ pattern Back xs x <-

{-# COMPLETE Empty, Back #-}

-- Deque smart constructor.
makeDeque :: [a] -> Int -> [Any] -> [a] -> Int -> [Any] -> RealTimeDeque a
makeDeque xs xlen xc ys ylen yc
-- Deque smart constructor, to use when it is possible the front list is too long.
makeDeque1 :: [a] -> Int -> [Any] -> [a] -> Int -> [Any] -> RealTimeDeque a
makeDeque1 xs xlen xc ys ylen yc
| xlen > (3 * ylen + 1) =
let xs1 = List.take xlen1 xs
ys1 = rotate1 xlen1 ys xs
in Q xs1 xlen1 (schedule xs1) ys1 ylen1 (schedule ys1)
in Q xs1 xlen1 (schedule xs1) ys1 (xlen + ylen - xlen1) (schedule ys1)
| otherwise = Q xs xlen xc ys ylen yc
where
xlen1 = (xlen + ylen) `unsafeShiftR` 1

-- Deque smart constructor, to use when it is possible the back list is too long.
makeDeque2 :: [a] -> Int -> [Any] -> [a] -> Int -> [Any] -> RealTimeDeque a
makeDeque2 xs xlen xc ys ylen yc
| ylen > (3 * xlen + 1) =
let xs1 = rotate1 ylen1 xs ys
ys1 = List.take ylen1 ys
Expand All @@ -147,11 +154,12 @@ makeDeque xs xlen xc ys ylen yc

rotate1 :: Int -> [a] -> [a] -> [a]
rotate1 i (x : xs) ys | i >= 3 = x : rotate1 (i - 3) xs (List.drop 3 ys)
rotate1 i xs ys = rotate2 xs (List.drop i ys) []
rotate1 i xs ys = rotate2 (List.drop i ys) [] xs

rotate2 :: [a] -> [a] -> [a] -> [a]
rotate2 [] ys zs = List.reverse ys ++ zs
rotate2 (x : xs) ys zs = x : rotate2 xs (List.drop 3 ys) (List.reverse (List.take 3 ys) ++ zs)
rotate2 ys zs = \case
[] -> List.reverse ys ++ zs
x : xs -> x : rotate2 (List.drop 3 ys) (List.reverse (List.take 3 ys) ++ zs) xs

-- | An empty double-ended queue.
empty :: RealTimeDeque a
Expand All @@ -161,26 +169,26 @@ empty =
-- | \(\mathcal{O}(1)\). Enqueue an element at the back of a double-ended queue.
enqueue :: a -> RealTimeDeque a -> RealTimeDeque a
enqueue y (Q xs xlen xc ys ylen yc) =
makeDeque xs xlen (execute1 xc) (y : ys) (ylen + 1) (execute1 yc)
makeDeque2 xs xlen (execute1 xc) (y : ys) (ylen + 1) (execute1 yc)

-- | \(\mathcal{O}(1)\). Enqueue an element at the front of a double-ended queue.
enqueueFront :: a -> RealTimeDeque a -> RealTimeDeque a
enqueueFront x (Q xs xlen xc ys ylen yc) =
makeDeque (x : xs) (xlen + 1) (execute1 xc) ys ylen (execute1 yc)
makeDeque1 (x : xs) (xlen + 1) (execute1 xc) ys ylen (execute1 yc)

-- | \(\mathcal{O}(1)\) front, \(\mathcal{O}(1)\) rest. Dequeue an element from the front of a double-ended queue.
dequeue :: RealTimeDeque a -> Maybe (a, RealTimeDeque a)
dequeue = \case
Q [] _ _ [] _ _ -> Nothing
Q [] _ _ (y : _) _ _ -> Just (y, empty)
Q (x : xs) xlen xc ys ylen yc -> Just (x, makeDeque xs (xlen - 1) (execute2 xc) ys ylen (execute2 yc))
Q (x : xs) xlen xc ys ylen yc -> Just (x, makeDeque2 xs (xlen - 1) (execute2 xc) ys ylen (execute2 yc))

-- | \(\mathcal{O}(1)\) back, \(\mathcal{O}(1)\) rest. Dequeue an element from of the back of a double-ended queue.
dequeueBack :: RealTimeDeque a -> Maybe (RealTimeDeque a, a)
dequeueBack = \case
Q [] _ _ [] _ _ -> Nothing
Q (x : _) _ _ [] _ _ -> Just (empty, x)
Q xs xlen xc (y : ys) ylen yc -> Just (makeDeque xs xlen (execute2 xc) ys (ylen - 1) (execute2 yc), y)
Q xs xlen xc (y : ys) ylen yc -> Just (makeDeque1 xs xlen (execute2 xc) ys (ylen - 1) (execute2 yc), y)

-- | \(\mathcal{O}(1)\). Is a double-ended queue empty?
isEmpty :: RealTimeDeque a -> Bool
Expand Down

0 comments on commit cb5defe

Please sign in to comment.