import Data.List.Split (splitOn) import qualified Data.Set as S type Coord = (Int, Int) globalY :: Int globalY = 2000000 parseCoord :: String -> Coord parseCoord xs = (read $ init x, read y) where [x,y] = map (drop 2) $ splitOn " " xs parseLine :: String -> (Coord, Coord) parseLine xs = (sensor, beacon) where [sensor, beacon] = map (parseCoord . dropWhile (/='x'))$ splitOn ":" xs manhattan :: Coord -> Coord -> Int manhattan (a,b) (x,y) = abs (a-x) + abs (b-y) allWithinRange :: Coord -> Coord -> S.Set Coord allWithinRange sensor@(a,b) beacon@(x,y) = S.fromList $ filter (\c -> manhattan sensor c <= dist) all where minx = a - dist maxx = a + dist miny = b - dist maxy = b + dist dist = manhattan sensor beacon all = [(x,y) | x <- [minx..maxx], y <- [globalY]] main :: IO () main = do x <- map parseLine . lines <$> getContents let beacons = S.fromList $ map snd x let reachable = foldr1 S.union $ map (uncurry allWithinRange) x let ys = S.size $ S.filter (\x -> snd x == globalY) (reachable S.\\ beacons) putStr "part 1: " print ys