···11+{-# LANGUAGE LambdaCase #-}
22+33+module Main where
44+55+import Control.Monad (liftM2)
66+import Data.Functor ((<&>))
77+import Data.List.Split (splitOn)
88+import Data.Map (Map)
99+import qualified Data.Map as M
1010+import System.Environment (getArgs)
1111+1212+parse n = ((a, b), (c, d))
1313+ where
1414+ [a, b, c, d] = map read $ concatMap (splitOn ",") $ splitOn " -> " n
1515+1616+doRange ((a, b), (c, d))
1717+ | a == c = map (a,) r2
1818+ | b == d = map (,b) r1
1919+ | otherwise = zip r1 r2
2020+ where
2121+ r1 = if a < c then [a .. c] else [a, a - 1 .. c]
2222+ r2 = if b < d then [b .. d] else [b, b - 1 .. d]
2323+2424+freqs = M.fromListWith (+) . map (,1)
2525+2626+solve = M.size . M.filter (> 1) . freqs . concatMap doRange
2727+2828+p1 = solve . filter (isHor |+ isVer)
2929+ where
3030+ isVer ((a, _), (c, _)) = a == c
3131+ isHor ((_, b), (_, d)) = b == d
3232+3333+p2 = solve
3434+3535+(|+) = liftM2 (||)
3636+3737+main = do
3838+ n <-
3939+ fmap (map parse . lines) $
4040+ getArgs
4141+ >>= \case
4242+ ["-"] -> getContents
4343+ [file] -> readFile file
4444+ print $ p1 n
4545+ print $ p2 n
+21
src/2021/06.lhs
···11+{-# LANGUAGE LambdaCase #-}
22+33+import Data.List.Split (splitOn)
44+import qualified Data.Map as M
55+import Data.Maybe (fromMaybe)
66+import System.Environment (getArgs)
77+88+grow m = M.insertWith (+) 6 new . M.insertWith (+) 8 new . M.mapKeys pred . M.delete 0 $ m
99+ where
1010+ new = fromMaybe 0 $ M.lookup 0 m
1111+1212+main = do
1313+ n <-
1414+ fmap (map read . splitOn ",") $
1515+ getArgs
1616+ >>= \case
1717+ ["-"] -> getContents
1818+ [file] -> readFile file
1919+ let fish = M.fromListWith (+) $ map (,1) n
2020+ print $ sum $ iterate grow fish !! 80
2121+ print $ sum $ iterate grow fish !! 256
+22
src/2021/07.lhs
···11+{-# LANGUAGE LambdaCase #-}
22+33+import Data.List.Split (splitOn)
44+import qualified Data.Map as M
55+import Data.Maybe (fromMaybe)
66+import System.Environment (getArgs)
77+88+cost1 = abs
99+1010+cost2 d = (d * d + abs d) `div` 2
1111+1212+solve cost n = minimum [sum (map (cost . subtract p) n) | p <- [minimum n .. maximum n]]
1313+1414+main = do
1515+ n <-
1616+ fmap (map read . splitOn ",") $
1717+ getArgs
1818+ >>= \case
1919+ ["-"] -> getContents
2020+ [file] -> readFile file
2121+ print $ solve cost1 n
2222+ print $ solve cost2 n
+48
src/2021/09.lhs
···11+{-# LANGUAGE LambdaCase #-}
22+33+import Data.Char (digitToInt)
44+import Data.List (sortBy)
55+import qualified Data.Map as M
66+import Data.Maybe (fromMaybe, mapMaybe)
77+import Data.Ord (Down (Down), comparing)
88+import qualified Data.Ord
99+import qualified Data.Set as S
1010+import System.Environment (getArgs)
1111+1212+grid lines =
1313+ M.fromList
1414+ [ ((x, y), digitToInt d)
1515+ | (y, l) <- zip [0 ..] lines,
1616+ (x, d) <- zip [0 ..] l
1717+ ]
1818+1919+around (x, y) = [(x + dx, y + dy) | (dx, dy) <- [(-1, 0), (1, 0), (0, -1), (0, 1)]]
2020+2121+minimas g = M.filterWithKey minima g
2222+ where
2323+ minima k a = a < minimum (mapMaybe (g M.!?) (around k))
2424+2525+-- generic bfs
2626+bfs :: (Num n, Ord a) => (a -> [a]) -> [a] -> [(a, n)]
2727+bfs next s = go S.empty (map (,0) s)
2828+ where
2929+ go _ [] = []
3030+ go seen ((x, dist) : xs)
3131+ | x `S.member` seen = go seen xs
3232+ | otherwise = (x, dist) : go (S.insert x seen) (xs ++ map (,dist + 1) (next x))
3333+3434+basin g m = bfs search [m]
3535+ where
3636+ search k = [a | a <- around k, Just v <- [M.lookup a g], v /= 9]
3737+3838+main = do
3939+ n <-
4040+ fmap lines $
4141+ getArgs
4242+ >>= \case
4343+ ["-"] -> getContents
4444+ [file] -> readFile file
4545+ let g = grid n
4646+ let m = minimas g
4747+ print $ sum m + length m
4848+ print $ product $ take 3 $ sortBy (comparing Down) $ length . basin g <$> M.keys m
+11
src/2021/10.lhs
···11+{-# LANGUAGE LambdaCase #-}
22+33+import System.Environment (getArgs)
44+55+main = do
66+ n <-
77+ fmap lines $
88+ getArgs >>= \case
99+ ["-"] -> getContents
1010+ [file] -> readFile file
1111+ print n