Advent of Code solutions
at main 61 lines 2.2 kB view raw
1{-# LANGUAGE FlexibleInstances #-} 2import Control.Monad 3import Data.Maybe 4 5tile :: Char -> Bool 6tile '#' = True 7tile '.' = False 8 9update :: Int -> Bool -> Bool 10update 2 True = True 11update 3 _ = True 12update _ _ = False 13 14class Remake i where 15 remake :: i -> i 16instance Remake Bool where 17 remake = const False 18instance (Functor f, Remake i) => Remake (f i) where 19 remake = fmap remake 20 21class Expand e where 22 expand :: e -> e 23instance (Remake e, Expand e) => Expand [e] where 24 expand e = remake (head a) : a ++ [remake (last a)] 25 where a = fmap expand e 26instance Expand Bool where 27 expand = id 28 29(!?) :: [a] -> Int -> Maybe a 30(!?) l x | x < 0 = Nothing 31(!?) l x | x >= length l = Nothing 32(!?) l x = Just (l !! x) 33 34cycleOnce :: [[[[Bool]]]] -> [[[[Bool]]]] 35cycleOnce state = run (expand state) 36 37neighbours :: [[[[Bool]]]] -> (Int, Int, Int, Int) -> Int 38neighbours space (x, y, z, w) = count [space !? ww >>= (!? zz) >>= (!? yy) >>= (!? xx) | xx <- [x-1..x+1], 39 yy <- [y-1..y+1], 40 zz <- [z-1..z+1], 41 ww <- [w-1..w+1], 42 xx /= x || yy /= y || zz /= z || ww /= w] 43 where count = length . filter id . catMaybes 44 45run :: [[[[Bool]]]] -> [[[[Bool]]]] 46run hyperspace = [[[[next (x, y, z, w) value | (x, value) <- [0..] `zip` row] 47 | (y, row) <- [0..] `zip` plane] 48 | (z, plane) <- [0..] `zip` space] 49 | (w, space) <- [0..] `zip` hyperspace] 50 where 51 next :: (Int, Int, Int, Int) -> Bool -> Bool 52 next = update . neighbours hyperspace 53 54cycles :: Int -> [[[[Bool]]]] -> [[[[Bool]]]] 55cycles 0 state = state 56cycles n state = cycles (n - 1) $ cycleOnce state 57 58main :: IO () 59main = do 60 contents <- fmap (fmap tile) . lines <$> getContents 61 print . length . filter id . join . join . join $ cycles 6 [[contents]]