1 import qualified Data.Map.Strict as M
2 import Text.ParserCombinators.ReadP
5 claims <- map parseClaim <$> lines <$> getContents
6 let layout = claimOverlap claims
7 let counts = M.fromListWith (+) . map (\v -> (v,1)) . M.elems $ layout
8 print $ counts M.! (-1)
9 print . index . head . filter (\c -> (fst . size $ c)*(snd . size $ c) == M.findWithDefault 0 (index c) counts) $ claims
11 data Claim = Claim { index :: Int
16 type ClaimMap = M.Map (Int, Int) Int
18 claimOverlap :: [Claim] -> ClaimMap
19 claimOverlap = foldl go M.empty . map claimedAreas
20 where cc :: Int -> Int -> Int
22 mn :: ClaimMap -> (Int, (Int, Int)) -> ClaimMap
23 mn cmap (v, k) = M.insertWith cc k v cmap
24 go :: ClaimMap -> [(Int, (Int, Int))] -> ClaimMap
25 go cmap = foldl mn cmap
27 claimedAreas :: Claim -> [(Int, (Int, Int))]
28 claimedAreas (Claim ind (cx, cy) (sx, sy)) =
29 [(ind,(i,j)) | i <- [cx+1..cx+sx], j <- [cy+1..cy+sy]]
31 parseClaim :: String -> Claim
32 parseClaim = fst . head . readP_to_S go
33 where digit :: ReadP Char
34 digit = satisfy (\char -> char >= '0' && char <= '9')
38 ind <- read <$> many1 digit
40 cx <- read <$> many1 digit
42 cy <- read <$> many1 digit
44 sx <- read <$> many1 digit
46 sy <- read <$> many1 digit
48 return (Claim ind (cx, cy) (sx, sy))
50 countV :: Eq a => a -> [a] -> Int
51 countV val = length . filter (== val)