Improves solution 3

master
Abhinav Sarkar 2018-12-05 23:34:39 +05:30
parent fc897f750f
commit f9cf2bedb4
1 changed files with 21 additions and 9 deletions

30
3/3.hs
View File

@ -3,8 +3,10 @@ module Main where
import Control.Applicative (some) import Control.Applicative (some)
import Data.Bits (Bits(shift)) import Data.Bits (Bits(shift))
import Data.Function (on)
import qualified Data.Set as Set
import qualified Data.Tree as T import qualified Data.Tree as T
import Data.List (maximumBy, foldl', nub) import Data.List (maximumBy, foldl', sort)
import Data.Ord (comparing) import Data.Ord (comparing)
import Text.Parsec hiding (Empty) import Text.Parsec hiding (Empty)
@ -15,7 +17,13 @@ data Rect = Rect { rectID :: Int
, rectTop :: Int , rectTop :: Int
, rectWidth :: Int , rectWidth :: Int
, rectHeight :: Int , rectHeight :: Int
} deriving (Eq) }
instance Eq Rect where
(==) = (==) `on` rectID
instance Ord Rect where
compare = compare `on` rectID
instance Show Rect where instance Show Rect where
show (Rect id l t w h) = "#" ++ show id ++ " " ++ show l ++ "," ++ show t ++ ":" ++ show (l+w) ++ "," ++ show (t+h) show (Rect id l t w h) = "#" ++ show id ++ " " ++ show l ++ "," ++ show t ++ ":" ++ show (l+w) ++ "," ++ show (t+h)
@ -60,7 +68,7 @@ bruteForceSolve rects =
---------------- Interval tree ---------------- ---------------- Interval tree ----------------
newtype Interval a = Interval (a,a) deriving (Eq) newtype Interval a = Interval { unInterval :: (a,a) } deriving (Eq, Ord)
instance Show a => Show (Interval a) where instance Show a => Show (Interval a) where
show (Interval (a, b)) = "<" ++ show a ++ "," ++ show b ++ ">" show (Interval (a, b)) = "<" ++ show a ++ "," ++ show b ++ ">"
@ -76,12 +84,12 @@ rightOf, leftOf :: Ord a => Interval a -> a -> Bool
rightOf (Interval (start, _)) x = x < start rightOf (Interval (start, _)) x = x < start
leftOf (Interval (_, end)) x = end <= x leftOf (Interval (_, end)) x = end <= x
insert :: (Ord a, Bits a, Num a) => (Interval a, b) -> IntervalTree a b -> IntervalTree a b insert :: (Ord a, Ord b, Bits a, Num a) => (Interval a, b) -> IntervalTree a b -> IntervalTree a b
insert o@(interval, _) tree = case tree of insert o@(interval, _) tree = case tree of
Empty start end -> go start end (start + half (end - start)) Empty start end -> go start end (start + half (end - start))
Node l center is r | interval `leftOf` center -> Node (insert o l) center is r Node l center is r | interval `leftOf` center -> Node (insert o l) center is r
Node l center is r | interval `rightOf` center -> Node l center is (insert o r) Node l center is r | interval `rightOf` center -> Node l center is (insert o r)
Node l center is r -> Node l center (o:is) r Node l center is r -> Node l center (sort (o:is)) r
where where
go start end center go start end center
| interval `leftOf` center = Node (insert o (Empty start center)) center [] (Empty center end) | interval `leftOf` center = Node (insert o (Empty start center)) center [] (Empty center end)
@ -95,16 +103,18 @@ includingIntervals interval = go []
where where
go acc t = case t of go acc t = case t of
Empty _ _ -> acc Empty _ _ -> acc
Node l center is r | interval `leftOf` center -> go (acc' is acc) l Node l _ is _ | not (null is) && interval `leftOf` leftmostStart is -> go acc l
Node l center is r | interval `rightOf` center -> go (acc' is acc) r Node l center is _ | interval `leftOf` center -> go (acc' is acc) l
Node l center is r -> go (go (acc' is acc) l) r Node _ center is r | interval `rightOf` center -> go (acc' is acc) r
Node l _ is r -> go (go (acc' is acc) l) r
where where
acc' is acc = filter (\(i,_) -> i `includes` interval) is ++ acc acc' is acc = filter (\(i,_) -> i `includes` interval) is ++ acc
leftmostStart = fst . unInterval . fst . head
includes (Interval (start1, end1)) (Interval (start2, end2)) includes (Interval (start1, end1)) (Interval (start2, end2))
= start1 <= start2 && end2 <= end1 = start1 <= start2 && end2 <= end1
fromList :: (Ord a, Bits a, Num a) => a -> a -> [(Interval a, b)] -> IntervalTree a b fromList :: (Ord a, Ord b, Bits a, Num a) => a -> a -> [(Interval a, b)] -> IntervalTree a b
fromList start end = foldl' (flip insert) (Empty start end) fromList start end = foldl' (flip insert) (Empty start end)
rectIntervalTrees :: [Rect] -> (IntervalTree Int Rect, IntervalTree Int Rect) rectIntervalTrees :: [Rect] -> (IntervalTree Int Rect, IntervalTree Int Rect)
@ -132,6 +142,8 @@ intervalTreeSolve rects =
nub . map snd nub . map snd
$ includingIntervals (Interval (x, x+1)) xTree ++ includingIntervals (Interval (y, y+1)) yTree $ includingIntervals (Interval (x, x+1)) xTree ++ includingIntervals (Interval (y, y+1)) yTree
nub = Set.toList . Set.fromList
main :: IO () main :: IO ()
main = do main = do
rects <- readInput . lines <$> getContents rects <- readInput . lines <$> getContents