import qualified Data.Map.Strict as Map import qualified Data.Set as Set main :: IO () main = do input <- lines <$> getContents let h = length input let w = length (head input) let inBounds (x, y) = 0 <= x && x < w && 0 <= y && y < h let indexed2 = zipWith (\y -> zipWith (\x -> ((x,y),)) [0::Int ..]) [0::Int ..] let pts = Map.fromListWith (++) . map (\(p, c) -> (c, [p])) . filter ((/= '.') . snd) $ concat (indexed2 input) let groups = map snd (Map.assocs pts) let (x,y) .+ (dx,dy) = (x+dx, y+dy) let (x,y) .- (dx,dy) = (x-dx, y-dy) let antinodes1 p q = let d = q .- p in filter inBounds [p .- d, q .+ d] let antinodes2 p q = let d = q .- p in takeWhile inBounds (iterate (.- d) p) ++ takeWhile inBounds (iterate (.+ d) q) let pairs [] = [] pairs (x:xs) = map (x,) xs ++ pairs xs print $ Set.size $ Set.fromList $ concatMap (concatMap (uncurry antinodes1) . pairs) groups print $ Set.size $ Set.fromList $ concatMap (concatMap (uncurry antinodes2) . pairs) groups