Advent of Code solutions

2021:9

+47
+18
2021/9/p1.hs
··· 1 + import Data.Array.Unboxed 2 + import Data.Char 3 + import Data.Maybe 4 + 5 + readGrid :: String -> Array (Int, Int) Int 6 + readGrid contents = listArray ((1, 1), (height, width)) $ concat input 7 + where 8 + input = fmap (fmap digitToInt) $ lines contents 9 + width = length $ input !! 0 10 + height = length input 11 + 12 + neighbours (y, x) = [(y - 1, x), (y + 1, x), (y, x + 1), (y, x - 1)] 13 + 14 + isMinPoint grid here = all (> (grid ! here)) $ mapMaybe (grid !?) (neighbours here) 15 + 16 + answer grid = sum $ fmap ((+ 1) . (grid !)) $ filter (isMinPoint grid) $ indices grid 17 + 18 + main = getContents >>= print . answer . readGrid
+29
2021/9/p2.hs
··· 1 + import Data.Array.Unboxed 2 + import Data.Char 3 + import Data.Maybe 4 + import Data.List (sortBy) 5 + import Data.Set qualified as Set 6 + 7 + readGrid :: String -> Array (Int, Int) Int 8 + readGrid contents = listArray ((1, 1), (height, width)) $ concat input 9 + where 10 + input = fmap (fmap digitToInt) $ lines contents 11 + width = length $ input !! 0 12 + height = length input 13 + 14 + neighbours (y, x) = [(y - 1, x), (y + 1, x), (y, x + 1), (y, x - 1)] 15 + 16 + isMinPoint grid here = all (> (grid ! here)) $ mapMaybe (grid !?) (neighbours here) 17 + 18 + basin grid origin = basin_ Set.empty origin 19 + where 20 + basin_ :: Set.Set (Int, Int) -> (Int, Int) -> Set.Set (Int, Int) 21 + basin_ co here 22 + | not $ inRange (bounds grid) here = co 23 + | grid ! here == 9 = co 24 + | Set.member here co = co 25 + | otherwise = foldl basin_ (Set.insert here co) (neighbours here) 26 + 27 + answer grid = product $ take 3 $ sortBy (flip compare) $ fmap (Set.size . basin grid) $ filter (isMinPoint grid) $ indices grid 28 + 29 + main = getContents >>= print . answer . readGrid