git.haldean.org aoc-2018 / d1cda62
a first pass at a solution but it doesn't work Haldean Brown 2 years ago
1 changed file(s) with 52 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
0 import Data.List
1 import qualified Data.Set as S
02 import Text.Parsec
13 import Text.Parsec.String
24
3 data Claim = Claim {
4 claimid :: Integer,
5 width :: Integer,
6 height :: Integer,
7 x :: Integer,
8 y :: Integer
9 } deriving Show
5 data Rect = Rect Int Int Int Int deriving Show
106
11 parseInt :: Parser Integer
12 parseInt = fmap (read :: String -> Integer) $ many1 digit
7 contains :: Rect -> Int -> Int -> Bool
8 contains (Rect rx ry rw rh) x y = rx <= x && x <= rx + rw && ry <= y && y <= ry + rh
9
10 bounding :: Rect -> Rect -> Rect
11 bounding (Rect x1 y1 w1 h1) (Rect x2 y2 w2 h2) =
12 let xmin = min x1 x2
13 xmax = max (x1 + w1) (x2 + w2)
14 ymin = min y1 y2
15 ymax = max (y1 + h1) (y2 + h2)
16 in Rect xmin ymin (xmax - xmin) (ymax - ymin)
17
18 data Claim = Claim Int Rect deriving Show
19 claimRect :: Claim -> Rect
20 claimRect (Claim _ rect) = rect
21
22 parseInt :: Parser Int
23 parseInt = fmap (read :: String -> Int) $ many1 digit
1324
1425 parseClaim :: Parser Claim
1526 parseClaim = do
2334 rw <- parseInt
2435 _ <- char 'x'
2536 rh <- parseInt
26 return Claim {claimid = rid, width = rw, height = rh, x = rx, y = ry}
37 return $ Claim rid (Rect rx ry rw rh)
38
39 readClaims :: String -> Either ParseError [Claim]
40 readClaims = parse (sepEndBy parseClaim (char '\n')) "input.txt"
41
42 findBounds :: [Claim] -> Rect
43 findBounds = (foldl1 bounding) . (map (\(Claim _ r) -> r))
44
45 allPointsInside :: Rect -> [(Int, Int)]
46 allPointsInside (Rect x y w h) =
47 let xs = enumFromTo x (x + w - 1)
48 ys = enumFromTo y (y + h - 1)
49 in concat $ map (\xx -> zip (repeat xx) ys) xs
50
51 allRelevantPoints :: [Claim] -> [(Int, Int)]
52 allRelevantPoints cs =
53 S.toList $ S.unions $ map (S.fromList . allPointsInside . claimRect) cs
54
55 getCounts :: [(Int, Int)] -> [Claim] -> [Int]
56 getCounts ps cs =
57 map (\(x, y) -> length $ filter (\(Claim _ cr) -> contains cr x y) cs) ps
58
59 getMultiCounted :: [Int] -> Int
60 getMultiCounted = length . (filter ((<) 1))
61
62 runMultiCounted :: [Claim] -> Int
63 runMultiCounted cs = getMultiCounted $ getCounts (allRelevantPoints cs) cs
2764
2865 main :: IO ()
29 main = fmap (parse (sepEndBy parseClaim (char '\n')) "") (readFile "input.txt") >>= print
66 main = do
67 claims <- fmap readClaims (readFile "input.txt")
68 case claims of
69 Right cs -> print $ runMultiCounted cs
70 Left err -> print err