--- /dev/null
+-- Writeup at https://work.njae.me.uk/2024/12/08/advent-of-code-2024-day-8/
+
+import AoC
+import Linear
+import Data.List
+import Data.Ix
+import qualified Data.Map.Strict as M
+
+type Position = V2 Int -- r, c
+type Bounds = (Position, Position)
+type Grid = M.Map Char [Position]
+
+main :: IO ()
+main =
+ do dataFileName <- getDataFileName
+ text <- readFile dataFileName
+ let (bounds, antennas) = mkGrid text
+ -- print antennas
+ -- print bounds
+ -- print $ allFreqAntinodes bounds antennas
+ -- print $ length $ nub $ concat $ M.elems $ allFreqAntinodes bounds antennas
+ print $ part1 bounds antennas
+ print $ part2 bounds antennas
+
+part1, part2 :: Bounds -> Grid -> Int
+part1 bounds antennas = length $ nub $ concat $ M.elems $ allFreqAntinodes bounds antennas
+part2 bounds antennas = length $ nub $ concat $ M.elems $ allFreqHarmonicAntinodes bounds antennas
+
+allFreqAntinodes, allFreqHarmonicAntinodes :: Bounds -> Grid -> Grid
+allFreqAntinodes bounds = M.map (antinodesOf bounds)
+allFreqHarmonicAntinodes bounds = M.map (harmonicAntinodesOf bounds)
+
+antinodesOf, harmonicAntinodesOf :: Bounds -> [Position] -> [Position]
+antinodesOf bounds ps =
+ filter (inRange bounds) [2 *^ a ^-^ b | a <- ps, b <- ps, a /= b]
+
+harmonicAntinodesOf bounds@(_, V2 kMax _) ps =
+ filter (inRange bounds) [ a ^+^ k *^ (a ^-^ b)
+ | a <- ps, b <- ps, a /= b
+ , k <- [0 .. kMax]]
+
+mkGrid :: String -> (Bounds, Grid)
+mkGrid text = ((V2 0 0, V2 rMax cMax),
+ foldl' go M.empty points)
+ where rows = lines text
+ rMax = length rows - 1
+ cMax = (length $ head rows) - 1
+ points = [ (rows !! r !! c, V2 r c)
+ | r <- [0..rMax], c <- [0..cMax]
+ , rows !! r !! c /= '.'
+ ]
+ go grid (f, pos) = M.insertWith (++) f [pos] grid
+
import: warnings, common-extensions, build-directives, common-modules
main-is: advent07/Main.hs
build-depends: attoparsec, text
+
+executable advent08
+ import: warnings, common-extensions, build-directives, common-modules
+ main-is: advent08/Main.hs
+ build-depends: linear, containers
\ No newline at end of file