Advent of Code solutions

2025 day 4

+84
+26
2025/4/p1.hs
··· 1 + import Data.List ((!?)) 2 + import Text.Parsec 3 + 4 + surrounding x y = 5 + [ (x - 1, y - 1), 6 + (x, y - 1), 7 + (x + 1, y - 1), 8 + (x - 1, y), 9 + (x + 1, y), 10 + (x - 1, y + 1), 11 + (x, y + 1), 12 + (x + 1, y + 1) 13 + ] 14 + 15 + answer input = 16 + length 17 + [ 1 | y <- [0 .. length grid - 1], 18 + x <- [0 .. (length $ grid !! y) - 1], 19 + grid !! y !! x == '@', 20 + length [1 | (x2, y2) <- surrounding x y, 21 + ((grid !? y2) >>= (!? x2)) == (Just '@')] < 4 22 + ] 23 + where 24 + Right grid = parse ((many $ oneOf "@.") `sepEndBy` char '\n') "" input 25 + 26 + main = getContents >>= print . answer
+27
2025/4/p1.tri
··· 1 + import "trilogy:debug" use dbg, tap 2 + import "trilogy:core" use length 3 + import "trilogy:io" use readall 4 + import "trilogy:grid" as grid 5 + import "trilogy:number" use im, re, swap 6 + import "trilogy:array" use map, filter 7 + import "trilogy:parsec" use parse, end_by, char, many, char_of 8 + 9 + func get g p = with g.(swap <| im p).(re p) when 'mia cancel '.' else yield 10 + 11 + proc main!() { 12 + let rows = parse (end_by (char '\n') <| many <| char_of "@.") readall!() 13 + let g = grid::from!(rows) 14 + 15 + let mut count = 0 16 + for pos:'@' in g { 17 + let around = grid::surrounding pos 18 + # TODO: something is wrong when passing the large record around, the runtime freezes 19 + # up. Accessing from the array here instead works a little better, but it's still way 20 + # too slow, and not linearly 21 + |> map (get rows) 22 + |> filter ((==) '@') 23 + |> length 24 + if around < 4 { count += 1 } 25 + } 26 + dbg!(count) 27 + }
+31
2025/4/p2.hs
··· 1 + import Data.List ((!?)) 2 + import Text.Parsec 3 + 4 + surrounding x y = 5 + [ (x - 1, y - 1), 6 + (x, y - 1), 7 + (x + 1, y - 1), 8 + (x - 1, y), 9 + (x + 1, y), 10 + (x - 1, y + 1), 11 + (x, y + 1), 12 + (x + 1, y + 1) 13 + ] 14 + 15 + at grid x y = case ((grid !? y) >>= (!? x)) of 16 + Just ch -> ch 17 + Nothing -> '.' 18 + 19 + isBlocked grid (x, y) = at grid x y == '@' 20 + 21 + clean grid = if cleaned == grid then grid else clean cleaned 22 + where 23 + cleaned = [[if at grid x y == '.' || (length $ filter (isBlocked grid) $ surrounding x y) < 4 then '.' else '@' | x <- [0 .. (length $ grid !! y) - 1]] | y <- [0 .. length grid - 1]] 24 + 25 + answer input = init - final 26 + where 27 + Right grid = parse ((many $ oneOf "@.") `sepEndBy` char '\n') "" input 28 + init = length $ filter ((==) '@') input 29 + final = length $ filter ((==) '@') $ concat $ (clean grid) 30 + 31 + main = getContents >>= print . answer