{-# Language ImportQualifiedPost, ViewPatterns, QuasiQuotes #-}
module Main where
import Advent (chunks, count, format)
import Data.List (transpose)
import Data.Map qualified as Map
main :: IO ()
IO ()
main =
do [(Grid, Grid)]
input <- [format|2017 21 ((.|#)+!&/ => (.|#)+!&/%n)*|]
let rules :: Grid -> Grid
rules = [(Grid, Grid)] -> Grid -> Grid
makeRules [(Grid, Grid)]
input
iterations :: [Grid]
iterations = (Grid -> Grid) -> Grid -> [Grid]
forall a. (a -> a) -> a -> [a]
iterate ((Grid -> Grid) -> Grid -> Grid
mapSubSquares Grid -> Grid
rules) Grid
start
Int -> IO ()
forall a. Show a => a -> IO ()
print (Grid -> Int
countCells ([Grid]
iterations [Grid] -> Int -> Grid
forall a. HasCallStack => [a] -> Int -> a
!! Int
5))
Int -> IO ()
forall a. Show a => a -> IO ()
print (Grid -> Int
countCells ([Grid]
iterations [Grid] -> Int -> Grid
forall a. HasCallStack => [a] -> Int -> a
!! Int
18))
type Grid = [[Char]]
start :: Grid
start :: Grid
start = [[Char]
".#.", [Char]
"..#", [Char]
"###"]
countCells :: Grid -> Int
countCells :: Grid -> Int
countCells = Char -> [Char] -> Int
forall (f :: * -> *) a. (Foldable f, Eq a) => a -> f a -> Int
count Char
'#' ([Char] -> Int) -> (Grid -> [Char]) -> Grid -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grid -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
similarSquares :: Grid -> [Grid]
similarSquares :: Grid -> [Grid]
similarSquares Grid
x = (Grid -> [Grid]) -> [Grid] -> [Grid]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Int -> [Grid] -> [Grid]
forall a. Int -> [a] -> [a]
take Int
4 ([Grid] -> [Grid]) -> (Grid -> [Grid]) -> Grid -> [Grid]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Grid -> Grid) -> Grid -> [Grid]
forall a. (a -> a) -> a -> [a]
iterate Grid -> Grid
rotateCCW) [Grid
x, Grid -> Grid
forall a. [a] -> [a]
reverse Grid
x]
rotateCCW :: Grid -> Grid
rotateCCW :: Grid -> Grid
rotateCCW = Grid -> Grid
forall a. [a] -> [a]
reverse (Grid -> Grid) -> (Grid -> Grid) -> Grid -> Grid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grid -> Grid
forall a. [[a]] -> [[a]]
transpose
mapSubSquares :: (Grid -> Grid) -> Grid -> Grid
mapSubSquares :: (Grid -> Grid) -> Grid -> Grid
mapSubSquares Grid -> Grid
rules Grid
xs =
(Grid -> Grid) -> [Grid] -> Grid
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap
((Grid -> [Char]) -> [Grid] -> Grid
forall a b. (a -> b) -> [a] -> [b]
map Grid -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([Grid] -> Grid) -> (Grid -> [Grid]) -> Grid -> Grid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Grid] -> [Grid]
forall a. [[a]] -> [[a]]
transpose ([Grid] -> [Grid]) -> (Grid -> [Grid]) -> Grid -> [Grid]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Grid -> Grid) -> [Grid] -> [Grid]
forall a b. (a -> b) -> [a] -> [b]
map Grid -> Grid
rules ([Grid] -> [Grid]) -> (Grid -> [Grid]) -> Grid -> [Grid]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Grid] -> [Grid]
forall a. [[a]] -> [[a]]
transpose ([Grid] -> [Grid]) -> (Grid -> [Grid]) -> Grid -> [Grid]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> Grid) -> Grid -> [Grid]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> [Char] -> Grid
forall a. Int -> [a] -> [[a]]
chunks Int
n))
(Int -> Grid -> [Grid]
forall a. Int -> [a] -> [[a]]
chunks Int
n Grid
xs)
where
n :: Int
n | Int -> Bool
forall a. Integral a => a -> Bool
even (Grid -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Grid
xs) = Int
2
| Bool
otherwise = Int
3
makeRules :: [(Grid,Grid)] -> Grid -> Grid
makeRules :: [(Grid, Grid)] -> Grid -> Grid
makeRules [(Grid, Grid)]
rs =
let rulesMap :: Map Grid Grid
rulesMap = [(Grid, Grid)] -> Map Grid Grid
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [ (Grid
k',Grid
v) | (Grid
k,Grid
v) <- [(Grid, Grid)]
rs , Grid
k' <- Grid -> [Grid]
similarSquares Grid
k ]
in (Map Grid Grid
rulesMap Map Grid Grid -> Grid -> Grid
forall k a. Ord k => Map k a -> k -> a
Map.!)