data Position = Pos {x::Int, y::Int} data PositionRotated = PosR {xR::Int, yR::Int} instance Show Position where show (Pos x y) = show (x,y) instance Show PositionRotated where show (PosR x y) = show (x,y) ++ "'" data Sensor = Sensor { position :: Position, beacon::Position } deriving Show data SensorRotated = SensorRotated { positionR :: PositionRotated, beaconR :: PositionRotated } deriving Show maxX (Sensor (Pos x _) (Pos x' _)) = maximum [x,x'] maxY (Sensor (Pos _ y) (Pos _ y')) = maximum [y,y'] class RotatePair a b where rotateS :: Int -> a -> b instance RotatePair Sensor SensorRotated where rotateS = rotateSensor instance RotatePair SensorRotated Sensor where rotateS = rotateSensor' rotate :: Int -> Position -> PositionRotated rotate width (Pos x y) = PosR (x+y) (width - x + y) rotate' :: Int -> PositionRotated -> Position rotate' width (PosR a b) = let y = ((b+a-width) `div` 2) in Pos (a-y) y -- parseLine :: String -> Sensor parseLine l = Sensor (Pos (read sx) (read sy)) (Pos (read bx) (read by)) where (sx,(_:_:_:_:ys)) = span(/=',') (drop (length "Sensor at x=") l) (sy,beaconLine) = span(/=':') ys (bx,(_:_:_:_:by)) = span(/=',') (drop (length ": closest beacon is at x=") beaconLine) parseInput = map parseLine.lines short = readFile "day15short" >>= pure.parseInput rotateSensor :: Int -> Sensor -> SensorRotated rotateSensor width (Sensor p b) = SensorRotated (rotate width p) (rotate width b) rotateSensor' :: Int -> SensorRotated -> Sensor rotateSensor' width (SensorRotated p b) = Sensor (rotate' width p) (rotate' width b) oneBeacon :: SensorRotated -> ((Int,Int),(Int, Int)) oneBeacon (SensorRotated (PosR x y) (PosR bx by)) = ((x-distance, y-distance),(x+distance, y+distance)) where distance = max (abs (x-bx)) (abs (y-by)) puzzle1 = do input <- short let (height, width) = (maximum $ map maxX input,maximum $ map maxY input) print (width, height) let rotatedSensors = map (rotateS width) input -- let relevantSensors = filter (relevant 10) rotatedSensors print rotatedSensors