|
| 1 | +{-# Language OverloadedStrings #-} |
| 2 | +{-| |
| 3 | +Module : Main |
| 4 | +Description : Day 24 solution |
| 5 | +Copyright : (c) Eric Mertens, 2019 |
| 6 | +License : ISC |
| 7 | + |
| 8 | +
|
| 9 | +<https://adventofcode.com/2019/day/24> |
| 10 | +
|
| 11 | +-} |
| 12 | +module Main (main) where |
| 13 | + |
| 14 | +import Advent |
| 15 | +import Advent.Coord |
| 16 | +import Data.Set (Set) |
| 17 | +import qualified Data.Set as Set |
| 18 | + |
| 19 | +main :: IO () |
| 20 | +main = |
| 21 | + do inp <- bugCoords <$> getInputLines 24 |
| 22 | + |
| 23 | + print (biodiversity (findDup (iterate update inp))) |
| 24 | + |
| 25 | + let inp3 = Set.map to3 inp |
| 26 | + print (Set.size (iterate update inp3 !! 200)) |
| 27 | + |
| 28 | +update :: (Ord a, Neighbors a) => Set a -> Set a |
| 29 | +update m = Set.filter rule |
| 30 | + $ Set.union m |
| 31 | + $ Set.fromList |
| 32 | + $ adjacents =<< Set.toList m |
| 33 | + where |
| 34 | + rule k = 1 == n || 2 == n && Set.notMember k m |
| 35 | + where n = count (`Set.member` m) (adjacents k) |
| 36 | + |
| 37 | +bugCoords :: [String] -> Set Coord |
| 38 | +bugCoords xs = Set.fromList [k | (k, '#') <- coordLines xs] |
| 39 | + |
| 40 | +biodiversity :: Set Coord -> Int |
| 41 | +biodiversity m = sum [ i | (i,k) <- zip (iterate (2*) 1) coords, Set.member k m] |
| 42 | + where |
| 43 | + coords = [C y x | y <- [0..4], x <- [0..4]] |
| 44 | + |
| 45 | +findDup :: Ord a => [a] -> a |
| 46 | +findDup = go Set.empty |
| 47 | + where |
| 48 | + go _ [] = error "no duplicates" |
| 49 | + go seen (x:xs) |
| 50 | + | Set.member x seen = x |
| 51 | + | otherwise = go (Set.insert x seen) xs |
| 52 | + |
| 53 | +class Neighbors a where adjacents :: a -> [a] |
| 54 | +instance Neighbors Coord where adjacents = filter inside . cardinal |
| 55 | +instance Neighbors C3 where adjacents = cardinal3 |
| 56 | + |
| 57 | +inside :: Coord -> Bool |
| 58 | +inside (C y x) = 0 <= x && 0 <= y && x < 5 && y < 5 |
| 59 | + |
| 60 | +------------------------------------------------------------------------ |
| 61 | +-- 3-dimensional recursive board coordinates |
| 62 | +------------------------------------------------------------------------ |
| 63 | + |
| 64 | +data C3 = C3 !Int !Int !Int |
| 65 | + deriving (Eq, Ord, Show) |
| 66 | + |
| 67 | +to3 :: Coord -> C3 |
| 68 | +to3 (C y x) = C3 0 y x |
| 69 | + |
| 70 | +cardinal3, left3, right3, above3, below3 :: C3 -> [C3] |
| 71 | + |
| 72 | +cardinal3 c = |
| 73 | + concat [left3 c, right3 c, above3 c, below3 c] |
| 74 | + |
| 75 | +left3 (C3 d y x) |
| 76 | + | x == 0 = [C3 (d-1) 2 1] |
| 77 | + | x == 3, y == 2 = [C3 (d+1) i 4 | i <- [0..4]] |
| 78 | + | otherwise = [C3 d y (x-1)] |
| 79 | + |
| 80 | +right3 (C3 d y x) |
| 81 | + | x == 4 = [C3 (d-1) 2 3] |
| 82 | + | x == 1, y == 2 = [C3 (d+1) i 0 | i <- [0..4]] |
| 83 | + | otherwise = [C3 d y (x+1)] |
| 84 | + |
| 85 | +below3 (C3 d y x) |
| 86 | + | y == 4 = [C3 (d-1) 3 2] |
| 87 | + | y == 1, x == 2 = [C3 (d+1) 0 i | i <- [0..4]] |
| 88 | + | otherwise = [C3 d (y+1) x] |
| 89 | + |
| 90 | +above3 (C3 d y x) |
| 91 | + | y == 0 = [C3 (d-1) 1 2] |
| 92 | + | y == 3, x == 2 = [C3 (d+1) 4 i | i <- [0..4]] |
| 93 | + | otherwise = [C3 d (y-1) x] |
0 commit comments