#! /usr/bin/env stack -- stack --resolver lts-12.20 --install-ghc script {-# LANGUAGE TupleSections #-} module Main where import qualified Data.Array as A import qualified Data.List as L import qualified Text.Parsec as P import qualified Text.Parsec.Language as PL import qualified Text.Parsec.Token as PT main :: IO () main = interact $ (show .) $ (. map parseLine . lines) $ \claims -> let outerRect = L.foldl1' merge (map claimArea claims) countArray = A.accumArray (+) 0 (rectBounds outerRect) $ concatMap (map (,1) . A.range . rectBounds . claimArea) claims in length $ filter (> 1) (A.elems countArray) data Rect = Rect { rectCol :: Int , rectRow :: Int , rectWidth :: Int , rectHeight :: Int } deriving (Eq, Show) rectBounds :: Rect -> ((Int, Int), (Int, Int)) rectBounds = ((,) <$> ((,) <$> rectRow <*> rectCol) <*> ((,) <$> ((+) <$> rectRow <*> subtract 1 . rectHeight) <*> ((+) <$> rectCol <*> subtract 1 . rectWidth))) data Claim = Claim { claimID :: Int , claimArea :: Rect } deriving (Eq, Show) merge (Rect c1 r1 w1 h1) (Rect c2 r2 w2 h2) = Rect cMin rMin (cMax - cMin) (rMax - rMin) where rMin = min r1 r2 cMin = min c1 c2 rMax = max (r1 + h1) (r2 + h2) cMax = max (c1 + w1) (c2 + w2) parseLine :: String -> Claim parseLine = either (error . show) id . P.runParser p () "" where decimal = fromInteger <$> PT.decimal PL.haskell whiteSpace = PT.whiteSpace PL.haskell p = Claim <$ P.char '#' <*> decimal <* whiteSpace <* P.char '@' <* whiteSpace <*> (Rect <$> decimal <* P.char ',' <*> decimal <* P.char ':' <* whiteSpace <*> decimal <* P.char 'x' <*> decimal)