diff options
author | Aria <me@aria.rip> | 2023-01-02 21:58:56 +0000 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-01-02 21:58:56 +0000 |
commit | 5eb58ad076f2cd435b11b140820da224b60b73d5 (patch) | |
tree | 2a67939595fbf993ff04f69b9cd3f0aa20827d96 /2021/day20/20.hs |
initial commit
Diffstat (limited to '2021/day20/20.hs')
-rw-r--r-- | 2021/day20/20.hs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/2021/day20/20.hs b/2021/day20/20.hs new file mode 100644 index 0000000..2798214 --- /dev/null +++ b/2021/day20/20.hs @@ -0,0 +1,61 @@ +module Main where + +import Data.List (foldl', intercalate) +import Data.Maybe (fromMaybe) + +type Picture = ([[Bool]], Bool) -- Visible region, colour of all pixels not visible + +readInteger :: [Bool] -> Int +readInteger = foldl' (\acc x -> acc * 2 + boolToDigit x) 0 + where boolToDigit True = 1 + boolToDigit False = 0 + +parseLine :: String -> [Bool] +parseLine = map charToBool + where charToBool '#' = True + charToBool '.' = False + +(!?) :: [a] -> Int -> Maybe a +xs !? n | n < 0 || n >= (length xs) = Nothing + | otherwise = Just (xs!!n) + +getPixel :: Picture -> Int -> Int -> Bool +getPixel (p, d) x y = fromMaybe d $ (p !? y) >>= (!? x) + +getNeighbours :: Picture -> Int -> Int -> [Bool] +getNeighbours p x y = [getPixel p (x + dx) (y + dy) | dy <- [(-1)..1], dx <- [(-1)..1]] + +getNewPixel :: Picture -> [Bool] -> Int -> Int -> Bool +getNewPixel p alg x y = alg !! (readInteger $ getNeighbours p x y) + +printPic :: Picture -> String +printPic = (intercalate "\n") . (map printLine) . fst + where printLine = map printBool + printBool True = '#' + printBool False = '.' + +newDefault :: Bool -> [Bool] -> Bool +newDefault True alg = alg!!511 +newDefault False alg = alg!!0 + +applyAlgorithm :: Picture -> [Bool] -> Picture +applyAlgorithm pic@(vis, def) alg = ([[getNewPixel pic alg x y | x <- [(-1)..mx]] | y <- [(-1)..my]], newDefault def alg) + where mx = length (vis!!0) + 1 + my = length vis + 1 + +parseFile :: String -> ([Bool], Picture) +parseFile s = (parseLine alg, (map parseLine ls, False)) + where (alg:_:ls) = lines s + +countPixels :: Picture -> Int +countPixels = foldr (+) 0 . map (length . filter id) . fst + +main :: IO () +main = do + input <- readFile "./input" + let (alg, pic) = parseFile input + let pic2 = foldr (\_ p -> applyAlgorithm p alg) pic [1..2] + putStrLn $ "Part 1: " ++ (show $ countPixels pic2) + + let pic50 = foldr (\_ p -> applyAlgorithm p alg) pic [1..50] + putStrLn $ "Part 2: " ++ (show $ countPixels pic50) |