AoC2018/Day03/Part1.hs

51 lines
1.9 KiB
Haskell
Executable File

#! /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)