Advertisement
NLinker

Задача №1005. Домой на электричках

Oct 16th, 2019
364
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 25.97 KB | None | 0 0
  1. {-# LANGUAGE RecordWildCards     #-}
  2. {-# LANGUAGE ScopedTypeVariables #-}
  3. {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
  4. {-# OPTIONS_GHC -fno-warn-unused-binds #-}
  5. {-# OPTIONS_GHC -fno-warn-unused-matches #-}
  6.  
  7. ----------------------
  8. -- The solution for --
  9. -- https://informatics.mccme.ru/moodle/mod/statements/view3.php?chapterid=1005#1
  10.  
  11. module Main where
  12.  
  13. import Control.Applicative (Applicative, pure, (<$>), (<*>))
  14. import Control.Exception   (handle, throwIO)
  15. import Control.Monad       (foldM, forM)
  16. import Data.Char           (isSpace)
  17. import Data.Foldable       (foldl')
  18. import Data.Function       (on)
  19. import Data.List           (sortBy)
  20. import Data.Maybe          (mapMaybe, fromJust)
  21. import Debug.Trace
  22. import Prelude             hiding (exp, lookup, null)
  23. import System.IO.Error     (isEOFError)
  24.  
  25. import qualified Data.ByteString.Char8 as BS
  26. import qualified Data.Map              as M
  27. import qualified Data.Set              as S
  28. import qualified Prelude               as P (foldr, null)
  29.  
  30. -- http://informatics.mccme.ru/moodle/mod/statements/view3.php?chapterid=1005#1
  31. type TimeTable = M.Map (Int, Int) Int
  32. data Ctx = Ctx
  33.  { n  :: Int -- total number of towns
  34.  , e  :: Int -- destination
  35.  , m  :: Int -- the number of routes
  36.  , tt :: TimeTable -- time table for the trains
  37.  } deriving (Eq, Show)
  38.  
  39. newtype Node = Node Int deriving (Eq, Ord, Show)
  40. newtype Dist = Dist Int deriving (Eq, Ord, Show)
  41.  
  42. -- Graph is the nodes and adjacency lists for all nodes
  43. data Graph = Graph
  44.  { nodes :: S.Set Node
  45.  , arcs  :: Arcs
  46.  } deriving (Show)
  47.  
  48. type Arcs = M.Map Node [(Node, Dist)]
  49. type Path = M.Map Node (Node, Dist)
  50. type Explored = S.Set Node
  51. type PrioQueue = PSQ Node Dist
  52.  
  53. main :: IO ()
  54. main = do
  55.  ctx <- parseCtx
  56.  len <- calc ctx
  57.  print len
  58.  
  59. ctx0 = Ctx
  60.  { n = 5
  61.  , e = 3
  62.  , m = 4
  63.  , tt = M.fromList
  64.   [ ((1,1),5),((1,2),10)
  65.   , ((2,2),10),((2,4),15)
  66.   , ((3,2),35),((3,3),20),((3,4),17),((3,5),0)
  67.   , ((4,1),2),((4,3),40),((4,4),45)
  68.   ]
  69.  }
  70.  
  71. -- result is -1
  72. ctx1 = Ctx
  73.  { n = 3
  74.  , e = 2
  75.  , m = 2
  76.  , tt = M.fromList
  77.   [ ((1,1),2),((1,2),20)
  78.   , ((2,2),17),((2,3),23)
  79.   ]
  80.  }
  81.  
  82. --undefined
  83.  
  84. -- useful functions
  85. -- mapMaybe :: (a -> Maybe b) -> [a] -> [b]
  86. -- on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
  87. -- compare :: Ord a => a -> a -> Ordering
  88. -- curry :: ((a, b) -> c) -> a -> b -> c
  89.  
  90. calc :: (Monad m) => Ctx -> m Int
  91. calc ctx@Ctx {..} = do
  92.  -- use monad to make the syntax nicer
  93.  g <- buildGraph ctx
  94.  -- traceShowM g
  95.  let col1 = buildCol ctx 1 -- all the nodes in the first column
  96.  let nes = buildCol ctx e -- all the nodes in the column e
  97.  if P.null col1 || P.null nes
  98.    then return (-1)
  99.      -- d0 = initial time delay
  100.    else do
  101.      let (x0, d0) = head col1
  102.      let initial = Node x0
  103.      path <- dijkstra g initial
  104.      -- path is like
  105.      --   fromList [ (Node 2, (Node 1, Dist 5)), (Node 7, (Node 2, Dist 0))]
  106.      -- find the minimum distance for all nodes in column e, if reachable
  107.      let ds = reachableDests path initial nes
  108.      return $ if P.null ds
  109.        then -1
  110.        else d0 + minimum ds
  111.  
  112. buildGraph :: Monad m => Ctx -> m Graph
  113. buildGraph ctx@Ctx{..} = do
  114.  let nodes = S.fromList $ map Node [1 .. m * n]
  115.  let arcs = buildArcs
  116.  return $ Graph nodes arcs
  117.  where
  118.    buildArcs = do
  119.      let mkEmpty x = (Node x, [] :: [(Node, Dist)])
  120.      let arcs0 = M.fromList $ map mkEmpty [1 .. m * n]
  121.      let arcs1 = foldl' updateArcsR arcs0 [1 .. m]
  122.       let arcs2 = foldl' updateArcsC arcs1 [1 .. n]
  123.      arcs2
  124.    -- go by rows and update arcs
  125.    updateArcsR as i = foldl' updateArcR as $ diffs $ buildRow ctx i
  126.     -- go by columns and update arcs
  127.     updateArcsC as j = foldl' updateArcC as $ diffs $ buildCol ctx j
  128.  
  129. reachableDests :: Path -> Node -> [(Int, t)] -> [Int]
  130. reachableDests path initial = mapMaybe $ calcDistance path initial . fstNode
  131.  where
  132.    fstNode (x, _) = Node x
  133.  
  134. -- path, initial node, final node
  135. calcDistance :: Path -> Node -> Node -> Maybe Int
  136. calcDistance path initial = calcD 0
  137.  where
  138.    calcD acc x1 =
  139.      if x1 == initial
  140.        then Just acc
  141.        else case M.lookup x1 path of
  142.          Nothing          -> Nothing
  143.          Just (x, Dist d) -> calcD (acc + d) x
  144.  
  145.  
  146. -- update arcs using horizontal cell pair
  147. updateArcR as (n1, n2, d) =
  148.  let n1s = fromJust $ M.lookup n1 as
  149.  in M.insert n1 ((n2, d) : n1s) as
  150.  
  151. -- update arcs using vertical cell pair
  152. updateArcC as (n1, n2, d) =
  153.    if d == Dist 0 then
  154.      -- insert two arcs, back and forward
  155.      let n1s = fromJust $ M.lookup n1 as in
  156.      let n2s = fromJust $ M.lookup n2 as in
  157.      M.insert n1 ((n2, d) : n1s) $
  158.        M.insert n2 ((n1, d) : n2s) as
  159.    else
  160.      let n1s = fromJust $ M.lookup n1 as in
  161.      M.insert n1 ((n2, d) : n1s) as
  162.  
  163. -- assumes the list is sorted by weights
  164. -- [((9,15),(14,17)),((14,17),(19,45))] -> [(Node 9,Node 14,Dist 2),(Node 14,Node 19,Dist 28)]
  165. diffs :: [(Int, Int)] -> [(Node, Node, Dist)]
  166. diffs xs =
  167.  let diffPair (n1, w1) (n2, w2) = (Node n1, Node n2, Dist $ w2 - w1)
  168.  in zipWith diffPair xs (tail xs)
  169.  
  170. -- return absolute node number
  171. -- e.g. for matrix 4x5
  172. -- cell (4,2) will be 17
  173. -- cell (3,5) will be 15
  174. cell :: Ctx -> Int -> Int -> Int
  175. cell ctx i j = (i - 1) * n ctx + j
  176.  
  177. buildRow :: Ctx -> Int -> [(Int, Int)]
  178. buildRow ctx@Ctx{..} i =
  179.  let select j = (\w -> (cell ctx i j, w)) `fmap` M.lookup (i, j) tt
  180.  in sortBy (compare `on` snd) $ mapMaybe select [1 .. n]
  181.  
  182. buildCol :: Ctx -> Int -> [(Int, Int)]
  183. buildCol ctx@Ctx{..} j =
  184.  let select i = (\w -> (cell ctx i j, w)) `fmap` M.lookup (i, j) tt
  185.  in sortBy (compare `on` snd) $ mapMaybe select [1 .. m]
  186.  
  187. -------------------------------------------------------
  188. --------------- Dijkstra Algorithm---------------------
  189. -------------------------------------------------------
  190. -- some test for the algorithm
  191. kickDijkstra :: IO ()
  192. kickDijkstra = do
  193.  let initial = Node 1
  194.  g <- loadGraph "dijkstra.txt"
  195.  traceShowM g
  196.  p <- dijkstra g initial
  197.  traceShowM p
  198.  
  199. infinity :: Dist
  200. infinity = Dist 999999999
  201.  
  202. dijkstra :: (Monad m) => Graph -> Node -> m Path
  203. dijkstra g initial = do
  204.  let rest = S.delete initial $ nodes g
  205.  let mkInf x = x :-> infinity
  206.  let heap = fromList $ (initial :-> Dist 0) : map mkInf (S.toList rest)
  207.  let path = M.singleton initial (initial, Dist 0) :: Path
  208.  mainLoop g heap S.empty M.empty
  209.  
  210. mainLoop :: (Monad m) => Graph -> PrioQueue -> Explored -> Path -> m Path
  211. mainLoop g heap exp path = do
  212.  let bind' = findMin heap
  213.   case bind' of
  214.    Nothing ->
  215.      return path
  216.    Just (mn :-> md) ->
  217.      -- warning: causes (Node 14,(Node 15,Dist 17)) which is wrong
  218.      -- if md == infinity then return path else
  219.      do
  220.        -- found minimal node with the distance
  221.        let heap1 = deleteMin heap
  222.        let arcs' = M.lookup mn (arcs g)
  223.         let (heap2, path2) = case arcs' of
  224.              -- lookup into arcs in g for min node failed
  225.              -- Nothing -> error "inconsistent data"
  226.              Nothing -> (heap1, path)
  227.              Just as ->
  228.                -- skip already explored nodes
  229.                let as1 = filter (\(n, _) -> S.notMember n exp) as in
  230.                (updateHeap heap1 md as1, updatePath path mn as1)
  231.        let exp2 = S.insert mn exp
  232.        -- traceShowM $ "node=(" ++ show mn ++ "," ++ show md ++ "\theap2=" ++ show heap2
  233.        mainLoop g heap2 exp2 path2
  234.  
  235. updatePath :: Path -> Node -> [(Node, Dist)] -> Path
  236. updatePath path minNode = foldl' yo path
  237.   where
  238.     yo :: Path -> (Node, Dist) -> Path
  239.     yo p (n, d) = M.insert n (minNode, d) p
  240.  
  241. -- updateHeap takes minDist to newly explored node,
  242. -- and list of all edges from the new node
  243. updateHeap :: PrioQueue -> Dist -> [(Node, Dist)] -> PrioQueue
  244. updateHeap heap minDist = foldl' go heap
  245.  where
  246.    -- e is the old distance was in the queue
  247.    up d e =
  248.      let Dist md = minDist in
  249.      let Dist nd = d in
  250.      min e $ Dist (md + nd)
  251.    go :: PrioQueue -> (Node, Dist) -> PrioQueue
  252.    go h (n, d) = adjust (up d) n h
  253.  
  254. -- Example file
  255. --1 2:10    3:20
  256. --2 4:15    5:50
  257. --3 4:30
  258. --4 5:30
  259. --5 6:5
  260. --6 7:2
  261. --7
  262. loadGraph :: String -> IO Graph
  263. loadGraph path = do
  264.  ls <- (map (BS.split '\t') . BS.lines) `fmap` BS.readFile path
  265.  let g = Graph S.empty M.empty
  266.  foldM processLine g ls
  267.  where
  268.    conv (x, y) = (Node x, Dist y)
  269.    processLine :: (Monad m) => Graph -> [BS.ByteString] -> m Graph
  270.    processLine g (x:xs) = do
  271.      let an = Node $ convert x
  272.      let as = map (conv . splitter) xs
  273.      let updateArcs old (n, d) =
  274.            case M.lookup an old of
  275.              Just ns -> M.insert an ((n, d):ns) old
  276.              Nothing -> M.insert an [] old
  277.      let updateDists old (n, d) = M.insert (an, n) d old
  278.      let nodes1 = S.insert an (nodes g)
  279.      let arcs1 = foldl' updateArcs (M.insert an [] $ arcs g) as
  280.       return $ Graph nodes1 arcs1
  281.     processLine g [] = error "processLine"
  282.  
  283. convert :: BS.ByteString -> Int
  284. convert = maybe (error "can't read Int") fst . BS.readInt
  285.  
  286. splitter :: BS.ByteString -> (Int, Int)
  287. splitter c = (convert x, convert y)
  288.   where
  289.     (x:y:_) = BS.split ':' c
  290.  
  291. -----------------------------------------------------------
  292. ------------------- stuff for parsing ---------------------
  293. -----------------------------------------------------------
  294. getWord :: IO String
  295. getWord =
  296.   handle handleEOF $ do
  297.     c <- getChar
  298.     if isSpace c
  299.       then return []
  300.       else (c :) <$> getWord
  301.   where
  302.     handleEOF e =
  303.       if isEOFError e
  304.         then return []
  305.         else throwIO e
  306.  
  307. readWord :: Read a => IO a
  308. readWord = getWord >>= readIO
  309.  
  310. readList :: Read a => String -> [a]
  311. readList = map read . words
  312.  
  313. -- carry the route number
  314. parseRoute :: Int -> IO (Int, [(Int,Int)])
  315. parseRoute ri = do
  316.   (ki :: Int) <- readWord
  317.   stops <-
  318.     forM [1 .. ki] $ \_ -> do
  319.       x <- readWord
  320.       y <- readWord
  321.       return (x, y)
  322.   return (ri, stops)
  323.  
  324. -- example input
  325. --5 3 4
  326. --2 1 5 2 10
  327. --2 2 10    4 15
  328. --4 2 35    3 20    4 17    5 0
  329. --3 1 2 3 40    4 45
  330. parseCtx :: IO Ctx
  331. parseCtx = do
  332.   n <- readWord
  333.   e <- readWord
  334.   m <- readWord
  335.   rawTts <- mapM parseRoute [1 .. m]
  336.   let tt = foldl' updateTt M.empty rawTts
  337.  return Ctx {..}
  338.  where
  339.    -- updateTt :: TimeTable -> (Int, [(Int, Int)]) -> TimeTable
  340.    updateTt tt (ri, stops) = foldl' (updateTtRow ri) tt stops
  341.     -- updateTtRow :: Int -> TimeTable -> (Int, Int) -> TimeTable
  342.     updateTtRow ri tt (i, t) = M.insert (ri, i) t tt
  343.  
  344.  
  345. -------------------------------------------------------
  346. --------------- Priority Queue ------------------------
  347. -------------------------------------------------------
  348. -- the priority queue is adapted from
  349. -- http://hackage.haskell.org/package/PSQueue-1.1/docs/src/Data-PSQueue.html
  350.  
  351. -- | @k :-> p@ binds the key @k@ with the priority @p@.
  352. data Binding k p = k :-> p deriving (Eq, Ord, Show, Read)
  353.  
  354. infix 0 :->
  355.  
  356. key  :: Binding k p -> k
  357. key  (k :-> _) =  k
  358.  
  359. prio :: Binding k p -> p
  360. prio (_ :-> p) =  p
  361.  
  362. data PSQ k p = Void | Winner k p (LTree k p) k
  363.  
  364. instance (Show k, Show p, Ord k, Ord p) => Show (PSQ k p) where
  365.   show = show . toAscList
  366.   --show Void = "[]"
  367.   --show (Winner k1 p lt k2) = "Winner "++show k1++" "++show p++" ("++show lt++") "++show k2
  368.  
  369. -- | /O(1)/ The number of bindings in a queue.
  370. size :: PSQ k p -> Int
  371. size Void              = 0
  372. size (Winner _ _ lt _) = 1 + size' lt
  373.  
  374. -- | /O(1)/ True if the queue is empty.
  375. null :: PSQ k p -> Bool
  376. null Void        = True
  377. null (Winner {}) = False
  378.  
  379. -- | /O(log n)/ The priority of a given key, or Nothing if the key is not
  380. -- bound.
  381. lookup :: (Ord k, Ord p) => k -> PSQ k p -> Maybe p
  382. lookup k q =
  383.  case tourView q of
  384.    Null -> fail "PSQueue.lookup: Empty queue"
  385.    Single k' p
  386.       | k == k'   -> return p
  387.      | otherwise -> fail "PSQueue.lookup: Key not found"
  388.    tl `Play` tr
  389.      | k <= maxKey tl -> lookup k tl
  390.      | otherwise      -> lookup k tr
  391.  
  392. empty :: (Ord k, Ord p) => PSQ k p
  393. empty = Void
  394.  
  395. -- | O(1) Build a queue with one binding.
  396. singleton :: (Ord k, Ord p) => k -> p -> PSQ k p
  397. singleton k p =  Winner k p Start k
  398.  
  399. -- | /O(log n)/ Insert a binding into the queue.
  400. insert :: (Ord k, Ord p) => k -> p -> PSQ k p -> PSQ k p
  401. insert k p q =
  402.  case tourView q of
  403.    Null -> singleton k p
  404.    Single k' p' ->
  405.      case compare k k' of
  406.         LT -> singleton k  p  `play` singleton k' p'
  407.         EQ -> singleton k  p
  408.         GT -> singleton k' p' `play` singleton k  p
  409.     tl `Play` tr
  410.       | k <= maxKey tl -> insert k p tl `play` tr
  411.       | otherwise      -> tl `play` insert k p tr
  412.  
  413. -- | /O(log n)/ Remove a binding from the queue.
  414. delete :: (Ord k, Ord p) => k -> PSQ k p -> PSQ k p
  415. delete k q =
  416.   case tourView q of
  417.     Null -> empty
  418.     Single k' p
  419.      | k == k'   -> empty
  420.       | otherwise -> singleton k' p
  421.    tl `Play` tr
  422.      | k <= maxKey tl -> delete k tl `play` tr
  423.      | otherwise      -> tl `play` delete k tr
  424.  
  425. -- | /O(log n)/ Adjust the priority of a key.
  426. adjust ::  (Ord p, Ord k) => (p -> p) -> k -> PSQ k p -> PSQ k p
  427. adjust f = adjustWithKey (\_ p -> f p)
  428.  
  429. -- | /O(log n)/ Adjust the priority of a key.
  430. adjustWithKey :: (Ord k, Ord p) => (k -> p -> p) -> k -> PSQ k p -> PSQ k p
  431. adjustWithKey f k q =
  432.  case tourView q of
  433.    Null -> empty
  434.    Single k' p
  435.       | k == k'   -> singleton k' (f k p)
  436.       | otherwise -> singleton k' p
  437.    tl `Play` tr
  438.      | k <= maxKey tl -> adjustWithKey f k tl `unsafePlay` tr
  439.      | otherwise      -> tl `unsafePlay` adjustWithKey f k tr
  440.  
  441. -- | /O(log n)/ The expression (@update f k q@) updates the
  442. -- priority @p@ bound @k@ (if it is in the queue). If (@f p@) is 'Nothing',
  443. -- the binding is deleted. If it is (@'Just' z@), the key @k@ is bound
  444. -- to the new priority @z@.
  445.  
  446. update :: (Ord k, Ord p) => (p -> Maybe p) -> k -> PSQ k p -> PSQ k p
  447. update f = updateWithKey (\_ p -> f p)
  448.  
  449. -- | /O(log n)/. The expression (@updateWithKey f k q@) updates the
  450. -- priority @p@ bound @k@ (if it is in the queue). If (@f k p@) is 'Nothing',
  451. -- the binding is deleted. If it is (@'Just' z@), the key @k@ is bound
  452. -- to the new priority @z@.
  453.  
  454. updateWithKey :: (Ord k, Ord p) => (k -> p -> Maybe p) -> k -> PSQ k p -> PSQ k p
  455. updateWithKey f k q =
  456.  case tourView q of
  457.    Null -> empty
  458.    Single k' p
  459.       | k==k' -> case f k p of
  460.                  Nothing -> empty
  461.                  Just p' -> singleton k p'
  462.      | otherwise -> singleton k' p
  463.     tl `Play` tr
  464.       | k <= maxKey tl -> updateWithKey f k tl `unsafePlay` tr
  465.       | otherwise      -> tl `unsafePlay` updateWithKey f k tr
  466.  
  467. -- | /O(n)/ The keys of a priority queue
  468. keys :: (Ord k, Ord p) => PSQ k p -> [k]
  469. keys = map key . toList
  470.  
  471. -- | /O(n log n)/ Build a queue from a list of bindings.
  472. fromList :: (Ord k, Ord p) => [Binding k p] -> PSQ k p
  473. fromList = P.foldr (\(k:->p) q -> insert k p q) empty
  474.  
  475. -- | /O(n)/ Build a queue from a list of bindings in order of
  476. -- ascending keys. The precondition that the keys are ascending is not checked.
  477. fromAscList :: (Ord k, Ord p) => [Binding k p] -> PSQ k p
  478. fromAscList = fromDistinctAscList . stripEq
  479.   where stripEq []     = []
  480.         stripEq (x:xs) = stripEq' x xs
  481.        stripEq' x' []     = [x']
  482.         stripEq' x' (x:xs)
  483.           | x' == x   = stripEq' x' xs
  484.          | otherwise = x' : stripEq' x xs
  485.  
  486. -- | /O(n)/ Build a queue from a list of distinct bindings in order of
  487. -- ascending keys. The precondition that keys are distinct and ascending is not checked.
  488. fromDistinctAscList :: (Ord k, Ord p) => [Binding k p] -> PSQ k p
  489. fromDistinctAscList = foldm unsafePlay empty . map (\(k:->p) -> singleton k p)
  490.  
  491. -- Folding a list in a binary-subdivision scheme.
  492. foldm :: (a -> a -> a) -> a -> [a] -> a
  493. foldm f e x
  494.  | P.null  x             = e
  495.  | otherwise             = fst (rek (length x) x)
  496.  where
  497.    rek 1 (a : as)    = (a, as)
  498.    rek n as          = (a1 `f` a2, as2)
  499.      where
  500.        m         = n `div` 2
  501.        (a1, as1) = rek (n - m) as
  502.        (a2, as2) = rek m       as1
  503.  
  504. -- | /O(n)/ Convert a queue to a list.
  505. toList :: (Ord k, Ord p) => PSQ k p -> [Binding k p]
  506. toList = toAscList
  507.  
  508. -- | /O(n)/ Convert a queue to a list in ascending order of keys.
  509. toAscList :: (Ord k, Ord p) => PSQ k p -> [Binding k p]
  510. toAscList q  = seqToList (toAscLists q)
  511.  
  512. toAscLists :: (Ord k, Ord p) => PSQ k p -> Sequ (Binding k p)
  513. toAscLists q = case tourView q of
  514.  Null         -> emptySequ
  515.  Single k p   -> singleSequ (k :-> p)
  516.  tl `Play` tr -> toAscLists tl <> toAscLists tr
  517.  
  518. -- | /O(n)/ Convert a queue to a list in descending order of keys.
  519. toDescList :: (Ord k, Ord p) => PSQ k p -> [ Binding k p ]
  520. toDescList q = seqToList (toDescLists q)
  521.  
  522. toDescLists :: (Ord k, Ord p) => PSQ k p -> Sequ (Binding k p)
  523. toDescLists q = case tourView q of
  524.  Null         -> emptySequ
  525.  Single k p   -> singleSequ (k :-> p)
  526.  tl `Play` tr -> toDescLists tr <> toDescLists tl
  527.  
  528.  
  529. -- | /O(1)/ The binding with the lowest priority.
  530. findMin :: (Ord k, Ord p) => PSQ k p -> Maybe (Binding k p)
  531. findMin Void             = Nothing
  532. findMin (Winner k p t m) = Just (k :-> p)
  533.  
  534. -- | /O(log n)/ Remove the binding with the lowest priority.
  535. deleteMin :: (Ord k, Ord p) => PSQ k p -> PSQ k p
  536. deleteMin Void             = Void
  537. deleteMin (Winner k p t m) = secondBest t m
  538.  
  539. -- | /O(log n)/ Retrieve the binding with the least priority, and the rest of
  540. -- the queue stripped of that binding.
  541. minView :: (Ord k, Ord p) => PSQ k p -> Maybe (Binding k p, PSQ k p)
  542. minView Void             = Nothing
  543. minView (Winner k p t m) = Just ( k :-> p , secondBest t m )
  544.  
  545. secondBest :: (Ord k, Ord p) => LTree k p -> k -> PSQ k p
  546. secondBest Start _m                  = Void
  547. secondBest (LLoser _ k p tl m tr) m' = Winner k p tl m `play` secondBest tr m'
  548. secondBest (RLoser _ k p tl m tr) m' = secondBest tl m `play` Winner k p tr m'
  549.  
  550.  
  551. -- | /O(r(log n - log r)/ @atMost p q@ is a list of all the bindings in @q@ with
  552. -- priority less than @p@, in order of ascending keys.
  553. -- Effectively,
  554. -- @  atMost p' q = filter (\\(k:->p) -> p<=p') . toList  @
  555. atMost :: (Ord k, Ord p) => p -> PSQ k p -> [Binding k p]
  556. atMost pt q = seqToList (atMosts pt q)
  557.  
  558. atMosts :: (Ord k, Ord p) => p -> PSQ k p -> Sequ (Binding k p)
  559. atMosts _pt Void  = emptySequ
  560. atMosts pt (Winner k p t _) =  prune k p t
  561.  where
  562.  prune _k _p _t
  563.    | p > pt         = emptySequ
  564.    | otherwise      = traverse k p t
  565.  traverse _k _p Start                     = singleSequ (k :-> p)
  566.  traverse _k _p (LLoser _ k' p' tl _m tr) = prune k' p' tl <> traverse k p tr
  567.  traverse _k _p (RLoser _ k' p' tl _m tr) = traverse k p tl <> prune k' p' tr
  568.  
  569. -- | /O(r(log n - log r))/ @atMostRange p (l,u) q@ is a list of all the bindings in
  570. -- @q@ with a priority less than @p@ and a key in the range @(l,u)@ inclusive.
  571. -- Effectively,
  572. -- @ atMostRange p' (l,u) q = filter (\\(k:->p) -> l<=k && k<=u ) . 'atMost' p' @
  573. atMostRange :: (Ord k, Ord p) => p -> (k, k) -> PSQ k p -> [Binding k p]
  574. atMostRange pt (kl, kr) q = seqToList (atMostRanges pt (kl, kr) q)
  575.  
  576. atMostRanges :: (Ord k, Ord p) => p -> (k, k) -> PSQ k p -> Sequ (Binding k p)
  577.  
  578. atMostRanges _pt _range Void = emptySequ
  579. atMostRanges pt range@(kl, kr) (Winner k p t _) = prune k p t
  580.  where
  581.  prune _k _p _t
  582.    | p > pt    = emptySequ
  583.    | otherwise = traverse k p t
  584.  traverse _k _p Start
  585.    | k `inrange` range = singleSequ (k :-> p)
  586.    | otherwise         = emptySequ
  587.  traverse _k _p (LLoser _ k' p' tl m tr) =
  588.    guard (kl <= m) (prune k' p' tl) <> guard (m <= kr) (traverse k p tr)
  589.  traverse _k _p (RLoser _ k' p' tl m tr) =
  590.    guard (kl <= m) (traverse k p tl) <> guard (m <= kr) (prune k' p' tr)
  591.  
  592. inrange :: (Ord a) => a -> (a, a) -> Bool
  593. a `inrange` (l, r)  =  l <= a && a <= r
  594.  
  595. ------- Internals -----
  596.  
  597. type Size = Int
  598. data LTree k p = Start
  599.               | LLoser {-# UNPACK #-}!Size !k !p (LTree k p) !k (LTree k p)
  600.               | RLoser {-# UNPACK #-}!Size !k !p (LTree k p) !k (LTree k p)
  601.  
  602. size' :: LTree k p -> Size
  603. size' Start                = 0
  604. size' (LLoser s _ _ _ _ _) = s
  605. size' (RLoser s _ _ _ _ _) = s
  606.  
  607. left, right :: LTree a b -> LTree a b
  608.  
  609. left  Start                  =  error "left: empty loser tree"
  610. left  (LLoser _ _ _ tl _ _ ) =  tl
  611. left  (RLoser _ _ _ tl _ _ ) =  tl
  612.  
  613. right Start                  =  error "right: empty loser tree"
  614. right (LLoser _ _ _ _  _ tr) =  tr
  615. right (RLoser _ _ _ _  _ tr) =  tr
  616.  
  617. maxKey :: PSQ k p -> k
  618. maxKey Void                =  error "maxKey: empty queue"
  619. maxKey (Winner _k _p _t m) =  m
  620.  
  621. lloser, rloser :: k -> p -> LTree k p -> k -> LTree k p -> LTree k p
  622. lloser k p tl m tr =  LLoser (1 + size' tl + size' tr) k p tl m tr
  623. rloser k p tl m tr =  RLoser (1 + size' tl + size' tr) k p tl m tr
  624.  
  625. --balance factor
  626. omega :: Int
  627. omega = 4
  628.  
  629. lbalance, rbalance ::
  630.  (Ord k, Ord p) => k-> p -> LTree k p -> k -> LTree k p -> LTree k p
  631.  
  632. lbalance k p l m r
  633.  | size' l + size' r < 2     = lloser        k p l m r
  634.  | size' r > omega * size' l = lbalanceLeft  k p l m r
  635.  | size' l > omega * size' r = lbalanceRight k p l m r
  636.  | otherwise               = lloser        k p l m r
  637.  
  638. rbalance k p l m r
  639.  | size' l + size' r < 2     = rloser        k p l m r
  640.  | size' r > omega * size' l = rbalanceLeft  k p l m r
  641.  | size' l > omega * size' r = rbalanceRight k p l m r
  642.  | otherwise               = rloser        k p l m r
  643.  
  644. lbalanceLeft  k p l m r
  645.  | size' (left r) < size' (right r) = lsingleLeft  k p l m r
  646.  | otherwise                      = ldoubleLeft  k p l m r
  647.  
  648. lbalanceRight k p l m r
  649.  | size' (left l) > size' (right l) = lsingleRight k p l m r
  650.  | otherwise                      = ldoubleRight k p l m r
  651.  
  652. rbalanceLeft  k p l m r
  653.  | size' (left r) < size' (right r) = rsingleLeft  k p l m r
  654.  | otherwise                      = rdoubleLeft  k p l m r
  655.  
  656. rbalanceRight k p l m r
  657.  | size' (left l) > size' (right l) = rsingleRight k p l m r
  658.  | otherwise                      = rdoubleRight k p l m r
  659.  
  660. lsingleLeft k1 p1 t1 m1 (LLoser _ k2 p2 t2 m2 t3)
  661.  | p1 <= p2  = lloser k1 p1 (rloser k2 p2 t1 m1 t2) m2 t3
  662.  | otherwise = lloser k2 p2 (lloser k1 p1 t1 m1 t2) m2 t3
  663. lsingleLeft _ _ _ _ Start = error "lsingleLeft"
  664.  
  665. lsingleLeft k1 p1 t1 m1 (RLoser _ k2 p2 t2 m2 t3) =
  666.  rloser k2 p2 (lloser k1 p1 t1 m1 t2) m2 t3
  667.  
  668. rsingleLeft k1 p1 t1 m1 (LLoser _ k2 p2 t2 m2 t3) =
  669.  rloser k1 p1 (rloser k2 p2 t1 m1 t2) m2 t3
  670. rsingleLeft _ _ _ _ Start = error "rsingleLeft"
  671.  
  672. rsingleLeft k1 p1 t1 m1 (RLoser _ k2 p2 t2 m2 t3) =
  673.  rloser k2 p2 (rloser k1 p1 t1 m1 t2) m2 t3
  674.  
  675. lsingleRight k1 p1 (LLoser _ k2 p2 t1 m1 t2) m2 t3 =
  676.  lloser k2 p2 t1 m1 (lloser k1 p1 t2 m2 t3)
  677. lsingleRight _ _ Start _ _ = error "lsingleRight"
  678.  
  679. lsingleRight k1 p1 (RLoser _ k2 p2 t1 m1 t2) m2 t3 =
  680.  lloser k1 p1 t1 m1 (lloser k2 p2 t2 m2 t3)
  681.  
  682. rsingleRight k1 p1 (LLoser _ k2 p2 t1 m1 t2) m2 t3 =
  683.  lloser k2 p2 t1 m1 (rloser k1 p1 t2 m2 t3)
  684. rsingleRight k1 p1 Start m2 t3 = error "rsingleRight"
  685.  
  686. rsingleRight k1 p1 (RLoser _ k2 p2 t1 m1 t2) m2 t3
  687.  | p1 <= p2  = rloser k1 p1 t1 m1 (lloser k2 p2 t2 m2 t3)
  688.  | otherwise = rloser k2 p2 t1 m1 (rloser k1 p1 t2 m2 t3)
  689.  
  690. ldoubleLeft k1 p1 t1 m1 (LLoser _ k2 p2 t2 m2 t3) =
  691.  lsingleLeft k1 p1 t1 m1 (lsingleRight k2 p2 t2 m2 t3)
  692. ldoubleLeft k1 p1 t1 m1 Start = error "ldoubleLeft"
  693.  
  694. ldoubleLeft k1 p1 t1 m1 (RLoser _ k2 p2 t2 m2 t3) =
  695.  lsingleLeft k1 p1 t1 m1 (rsingleRight k2 p2 t2 m2 t3)
  696.  
  697. ldoubleRight k1 p1 (LLoser _ k2 p2 t1 m1 t2) m2 t3 =
  698.  lsingleRight k1 p1 (lsingleLeft k2 p2 t1 m1 t2) m2 t3
  699. ldoubleRight k1 p1 Start m2 t3 = error "ldoubleRight"
  700.  
  701. ldoubleRight k1 p1 (RLoser _ k2 p2 t1 m1 t2) m2 t3 =
  702.  lsingleRight k1 p1 (rsingleLeft k2 p2 t1 m1 t2) m2 t3
  703.  
  704. rdoubleLeft k1 p1 t1 m1 (LLoser _ k2 p2 t2 m2 t3) =
  705.  rsingleLeft k1 p1 t1 m1 (lsingleRight k2 p2 t2 m2 t3)
  706. rdoubleLeft k1 p1 t1 m1 Start = error "rdoubleLeft"
  707.  
  708. rdoubleLeft k1 p1 t1 m1 (RLoser _ k2 p2 t2 m2 t3) =
  709.  rsingleLeft k1 p1 t1 m1 (rsingleRight k2 p2 t2 m2 t3)
  710.  
  711. rdoubleRight k1 p1 (LLoser _ k2 p2 t1 m1 t2) m2 t3 =
  712.  rsingleRight k1 p1 (lsingleLeft k2 p2 t1 m1 t2) m2 t3
  713. rdoubleRight k1 p1 Start m2 t3 = error "rdoubleRight"
  714.  
  715. rdoubleRight k1 p1 (RLoser _ k2 p2 t1 m1 t2) m2 t3 =
  716.  rsingleRight k1 p1 (rsingleLeft k2 p2 t1 m1 t2) m2 t3
  717.  
  718. play :: (Ord k, Ord p) => PSQ k p -> PSQ k p -> PSQ k p
  719.  
  720. Void `play` t' = t'
  721. t `play` Void  = t
  722.  
  723. Winner k p t m  `play`  Winner k' p' t' m'
  724.  | p <= p'   = Winner k  p  (rbalance k' p' t m t') m'
  725.   | otherwise = Winner k' p' (lbalance k  p  t m t') m'
  726.  
  727. unsafePlay :: (Ord k, Ord p) => PSQ k p -> PSQ k p -> PSQ k p
  728.  
  729. Void `unsafePlay` t' =  t'
  730. t `unsafePlay` Void  =  t
  731.  
  732. Winner k p t m  `unsafePlay`  Winner k' p' t' m'
  733.   | p <= p'   = Winner k  p  (rbalance k' p' t m t') m'
  734.  | otherwise = Winner k' p' (lbalance k  p  t m t') m'
  735.  
  736. data TourView k p = Null | Single k p | PSQ k p `Play` PSQ k p
  737.  
  738. tourView :: (Ord k) => PSQ k p -> TourView k p
  739.  
  740. tourView Void                  =  Null
  741. tourView (Winner k p Start _m) =  Single k p
  742.  
  743. tourView (Winner k p (RLoser _ k' p' tl m tr) m') =
  744.   Winner k  p  tl m `Play` Winner k' p' tr m'
  745.  
  746. tourView (Winner k p (LLoser _ k' p' tl m tr) m') =
  747.   Winner k' p' tl m `Play` Winner k  p  tr m'
  748.  
  749. -- Hughes's efficient sequence type --
  750.  
  751. emptySequ  :: Sequ a
  752. singleSequ :: a -> Sequ a
  753. (<>)       :: Sequ a -> Sequ a -> Sequ a
  754. seqFromList   :: [a] -> Sequ a
  755. seqFromListT  :: ([a] -> [a]) -> Sequ a
  756. seqToList     :: Sequ a -> [a]
  757.  
  758. infixr 5 <>
  759.  
  760. newtype Sequ a  =  Sequ ([a] -> [a])
  761.  
  762. emptySequ = Sequ id
  763. singleSequ a = Sequ (\as -> a : as)
  764. Sequ x1 <> Sequ x2 = Sequ (x1 . x2)
  765. seqFromList as = Sequ (\as' -> as ++ as')
  766. seqFromListT = Sequ
  767. seqToList (Sequ x) = x []
  768.  
  769. instance Show a => Show (Sequ a) where
  770.     showsPrec d a = showsPrec d (seqToList a)
  771.  
  772. guard :: Bool -> Sequ a -> Sequ a
  773. guard False _as = emptySequ
  774. guard True  as  = as
  775.  
  776.  
  777. -- ---------------------------------------------------------------------------
  778. -- Identity instances for Functor and Monad
  779.  
  780. newtype Identity a = Identity { runIdentity :: a }
  781.  
  782. instance Functor Identity where
  783.     fmap f m = Identity (f (runIdentity m))
  784.  
  785. instance Applicative Identity where
  786.     pure = Identity
  787.     (<*>) (Identity f) (Identity a) = Identity (f a)
  788.  
  789. instance Monad Identity where
  790.     return = Identity
  791.     m >>= k  = k (runIdentity m)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement