DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 17: Conway Cubes

Collapse
 
bgaster profile image
Benedict Gaster

Tried for ages to get a generic solution for an dim size, but in the end failed in the most part! Anywhy here's a Haskell soution:

type Grid a = S.Set a

class Ord a => GridN a where
  neighbours :: S.Set a -> M.Map a Int

instance GridN (Int,Int,Int) where
    neighbours s = 
        let m = M.fromSet (const 1) s
            idxs = Prelude.filter (\(x,y,z) -> x /= 0 || y /= 0 || z /= 0) $ 
                      [(-1,,), (0,,), (1,,)] <*> [-1, 0, 1] <*> [-1, 0, 1]
            keys = map (\(dx,dy,dz) -> M.mapKeys (\(x,y,z) -> (x+dx, y+dy, z+dz)) m) idxs
        in M.unionsWith (+) keys

instance GridN (Int,Int,Int,Int) where
      neighbours s = 
        let m = M.fromSet (const 1) s
            idxs = Prelude.filter (\(x,y,z,w) -> x /= 0 || y /= 0 || z /= 0 || w /= 0) $ 
                      ((,,,) <$> [-1, 0, 1]) <*> [-1, 0, 1] <*> [-1, 0, 1] <*> [-1, 0, 1]
            keys = map (\(dx,dy,dz,dw) -> M.mapKeys (\(x,y,z,w) -> (x+dx, y+dy, z+dz, w+dw)) m) idxs
        in M.unionsWith (+) keys

parse :: String -> Grid (Int,Int,Int)
parse = parse' 0 0 S.empty
    where
        parse' x y s (c:cs) = case c of
            '#'  -> parse' (x+1) y (S.insert (x, y, 0::Int) s) cs
            '.'  -> parse' (x+1) y s cs
            '\n' -> parse' 0 (y+1) s cs
        parse' _ _ s [] = s

step nbours s  = let ns = nbours s
                 in  S.union (M.keysSet $ M.filter (`elem` [2, 3]) (ns `M.restrictKeys` s))
                             (M.keysSet $ M.filter (== 3) (ns `M.withoutKeys` s))

task1 :: Grid (Int,Int,Int) -> Int
task1 = S.size . (!! 6) . iterate (step neighbours)

task2 :: Grid (Int,Int,Int,Int) -> Int
task2 = S.size . (!! 6) . iterate (step neighbours)

main  = do
  is <- readFile "day17_input" <&> parse
  print (task1 is)
  print (task2 $ S.map (\(x, y, z) -> (x, y, z, 0)) is)
Enter fullscreen mode Exit fullscreen mode