import Data.List main :: IO () main = do input <- readFile "input" let grid = lines input let antennas = getAntennas grid let nodes = filter (isInBounds (gridBounds grid) ) . nub . flatten . map (getAntinodes (gridBounds grid)) . groupAntennas $ antennas print $ length nodes isInBounds (h,w) (y,x) = y >= 0 && y < h && x >= 0 && x < w getAntinodes bounds coords = let n = length coords in flatten [drawLine bounds (coords!!j) (coords!!i) | i <- [0..n-1], j <- [0..i-1]] drawLine bounds (y1,x1) (y2,x2) = let (dy,dx) = reduce (y2-y1,x2-x1) in (takeWhile (isInBounds bounds) [(y1+i*dy,x1+i*dx) | i <- [0..]]) ++ (takeWhile (isInBounds bounds) [(y1-i*dy,x1-i*dx) | i <- [0..]]) groupAntennas = map (map snd) . groupBy (\a b -> fst a == fst b) . sortOn fst flatten l = foldl (++) [] l gridBounds grid = (length grid, length (head grid)) getAntennas grid = let (n,m) = gridBounds grid in [(grid!!i!!j, (i,j)) | i <- [0..n-1], j <- [0..m-1], grid!!i!!j /= '.'] reduce (n,d) = let g = gcd (abs n) (abs d) in (n `div` g, d `div` g)