git.haldean.org
a first pass at a solution but it doesn't work Haldean Brown 3 years ago
1 changed file(s) with 52 addition(s) and 11 deletion(s).
 0 import Data.List 1 import qualified Data.Set as S 0 2 import Text.Parsec 1 3 import Text.Parsec.String 2 4 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 10 6 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 13 24 14 25 parseClaim :: Parser Claim 15 26 parseClaim = do 23 34 rw <- parseInt 24 35 _ <- char 'x' 25 36 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 27 64 28 65 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