summaryrefslogtreecommitdiff
path: root/day08/day08.hs
diff options
context:
space:
mode:
authorNat Lasseter <user@4574.co.uk>2024-12-08 17:01:16 +0000
committerNat Lasseter <user@4574.co.uk>2024-12-08 17:01:16 +0000
commitb30ffe15b486fc82665b52c8b8bdcfc58c2bf0d4 (patch)
tree6e12d7981f60134e1fd02337f66ee4e32f02de1c /day08/day08.hs
parent1d41bdb5e3807c366c6a38c6233377a2721b9a1f (diff)
[Day 08] Done
Diffstat (limited to 'day08/day08.hs')
-rw-r--r--day08/day08.hs83
1 files changed, 83 insertions, 0 deletions
diff --git a/day08/day08.hs b/day08/day08.hs
new file mode 100644
index 0000000..728dd71
--- /dev/null
+++ b/day08/day08.hs
@@ -0,0 +1,83 @@
+import Data.List
+
+type Vec = (Int, Int)
+type Ant = (Int, Int, Char)
+type Map = (Vec, [Ant])
+
+consume2 :: [Ant] -> Int -> Int -> [Char] -> [Ant]
+consume2 acc _ _ [] = acc
+consume2 acc r c ('.':t) = consume2 acc r (c+1) t
+consume2 acc r c (h:t) = consume2 ((r, c, h):acc) r (c+1) t
+
+consume1 :: [Ant] -> Int -> [[Char]] -> [Ant]
+consume1 acc _ [] = acc
+consume1 acc r (h:t) = consume1 (acc ++ (consume2 [] r 0 h)) (r+1) t
+
+consume :: [Char] -> Map
+consume file =
+ ((length grid, length $ head grid), consume1 [] 0 grid)
+ where grid = lines file
+
+neg :: Vec -> Vec
+neg (r, c) = (-r, -c)
+add :: Vec -> Vec -> Vec
+add (fr, fc) (dr, dc) = (fr + dr, fc + dc)
+scale :: Int -> Vec -> Vec
+scale m (r, c) = (r * m, c * m)
+path :: (Vec, Vec) -> Vec
+path (f, t) = add t $ neg f
+
+inside :: Vec -> Vec -> Bool
+inside (mr, mc) (r, c) =
+ r >= 0 && r < mr && c >= 0 && c < mc
+
+simplify :: Vec -> Vec
+simplify (r, c) =
+ (r `div` d, c `div` d)
+ where d = gcd r c
+
+antiNodes :: Map -> Char -> [Vec]
+antiNodes (size, ants) freq =
+ filter (inside size) $ map (\p@(f, _) -> add f $ scale 2 $ path p) pairs
+ where
+ fants = filter (\(_, _, f) -> f == freq) ants
+ coos = map (\(r, c, _) -> (r, c)) fants
+ pairs = [(a1, a2) | a1 <- coos, a2 <- coos, a1 /= a2]
+
+antiNodes22 :: [Vec] -> Vec -> Vec -> Vec -> [Vec]
+antiNodes22 acc size from del
+ | inside size nxt = antiNodes22 (nxt:acc) size nxt del
+ | otherwise = acc
+ where nxt = add from del
+
+antiNodes21 :: Vec -> (Vec, Vec) -> [Vec]
+antiNodes21 s p@(f, t) =
+ antiNodes22 [] s f d ++
+ [f] ++
+ antiNodes22 [] s f (neg d)
+ where
+ d = simplify $ path p
+
+antiNodes2 :: Map -> Char -> [Vec]
+antiNodes2 (size, ants) freq =
+ nub $ concat $ map (antiNodes21 size) pairs
+ where
+ fants = filter (\(_, _, f) -> f == freq) ants
+ coos = map (\(r, c, _) -> (r, c)) fants
+ pairs = [(a1, a2) | a1 <- coos, a2 <- coos, a1 /= a2]
+
+part1 mp@(_, ants) =
+ length $ nub $ concat $ map (antiNodes mp) freqs
+ where
+ freqs = nub $ map (\(_, _, f) -> f) ants
+
+part2 mp@(_, ants) =
+ length $ nub $ concat $ map (antiNodes2 mp) freqs
+ where
+ freqs = nub $ map (\(_, _, f) -> f) ants
+
+main = do
+ file <- readFile "day08.input"
+ let mp = consume file
+ putStrLn ("Part 1: " ++ (show $ part1 mp))
+ putStrLn ("Part 2: " ++ (show $ part2 mp))