aoc2022/15-a.hs

51 lines
1.3 KiB
Haskell

{-# LANGUAGE TupleSections #-}
import Common
import Data.List.Split (splitOn)
import Data.List (find)
import Data.Char (isNumber)
import Data.Maybe (isJust)
type SensorData = (Pos, Int)
parseLine :: String -> SensorData
parseLine l = (sensorPos, sensorPos `taxicabDist` beaconPos)
where
sensorPos = getPos left
beaconPos = getPos right
getPos :: String -> Pos
getPos s = (x, y)
where [x, y] = map (read . filter isNumber) $ filter (isJust . find isNumber) $ words s
[left, right] = splitOn ":" l
scanY :: Int
scanY = 2000000
getMinX :: SensorData -> Int
getMinX ((x, y), dist) = x - dist
getMaxX :: SensorData -> Int
getMaxX ((x, y), dist) = x + dist
getXScanRange :: [SensorData] -> (Int, Int)
getXScanRange sensors = (minX, maxX)
where
minX = minimum $ map getMinX sensors
maxX = maximum $ map getMaxX sensors
-- manual recursion for extra speed
canContainBeacon :: [SensorData] -> Pos -> Bool
canContainBeacon ((sensorPos, sensorRange):xs) p = p `taxicabDist` sensorPos > sensorRange && (canContainBeacon xs p)
canContainBeacon [] _ = True
countContainsBeacon :: [SensorData] -> Int
countContainsBeacon sensors = count (not . canContainBeacon sensors) $ map (, scanY) [minX .. maxX]
where
(minX, maxX) = getXScanRange sensors
main = interact $
show
. flip (-) 1
. countContainsBeacon
. map parseLine
. lines