From 51842c43509f0c5d31d80ecc4ac87c5a36ac3928 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Sat, 11 Dec 2021 16:35:10 +0200 Subject: Day 11 --- day11/input.txt | 10 +++++ day11/main.hs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ day11/simple1.txt | 5 +++ day11/simple2.txt | 5 +++ day11/test.txt | 10 +++++ utils.hs | 7 +++- 6 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 day11/input.txt create mode 100644 day11/main.hs create mode 100644 day11/simple1.txt create mode 100644 day11/simple2.txt create mode 100644 day11/test.txt diff --git a/day11/input.txt b/day11/input.txt new file mode 100644 index 0000000..add3348 --- /dev/null +++ b/day11/input.txt @@ -0,0 +1,10 @@ +5251578181 +6158452313 +1818578571 +3844615143 +6857251244 +2375817613 +8883514435 +2321265735 +2857275182 +4821156644 diff --git a/day11/main.hs b/day11/main.hs new file mode 100644 index 0000000..a3ec51e --- /dev/null +++ b/day11/main.hs @@ -0,0 +1,110 @@ +module Main where + +import Control.Monad (foldM) +import Data.Char (digitToInt) +import Data.Either (fromLeft) +import Data.List (foldl', intercalate) +import Data.Map (Map, (!)) +import qualified Data.Map as Map +import Debug.Trace (trace, traceShow) +import Utils + +type Dim = (Int, Int) + +type Point = (Int, Int) + +type State = Map Point Int + +printState :: Dim -> State -> IO () +printState dim@(xsize, ysize) state = + let coords = [(x, y) | y <- [0 .. ysize - 1], x <- [0 .. xsize -1]] + elems = coords $> map (state !) + in splitEvery xsize (elems $> map show .> intercalate "") + $> map putStrLn + .> sequence_ + +pointSum :: Point -> Point -> Point +pointSum (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) + +incAllBy1 :: State -> State +incAllBy1 = Map.map (+ 1) + +flash :: State -> Dim -> Point -> State +flash state dim@(xsize, ysize) p = + let flashed = neighbors state dim p + in Map.mapWithKey (\p' v -> if p' `elem` flashed then v + 1 else v) state + +findOverNine :: State -> [Point] -> Maybe Point +findOverNine state alreadyFlashed = + let ps = Map.filterWithKey (\k v -> v > 9 && k `notElem` alreadyFlashed) state $> Map.keys + in if not (null ps) + then Just (head ps) + else Nothing + +resetFlashed :: State -> State +resetFlashed = Map.map (\v -> if v > 9 then 0 else v) + +neighbors :: State -> Dim -> Point -> [Point] +neighbors state (xsize, ysize) p@(x, y) = + let diffs = [(dx, dy) | dx <- [-1, 0, 1], dy <- [-1, 0, 1]] + ps = diffs $> map (pointSum p) + in filter (`Map.member` state) ps + +flashIfNotYetFlashed :: State -> Dim -> [Point] -> Point -> ([Point], State) +flashIfNotYetFlashed state dim alreadyFlashed p + | p `elem` alreadyFlashed = (alreadyFlashed, state) + | otherwise = + let state' = flash state dim p + in (p : alreadyFlashed, state') + +iterateFlashes state dim alreadyFlashed = + let unstableM = findOverNine state alreadyFlashed + in case unstableM of + Nothing -> (length alreadyFlashed, state) + Just p -> + let (alreadyFlashed', state') = flashIfNotYetFlashed state dim alreadyFlashed p + (n, res) = iterateFlashes state' dim alreadyFlashed' + in if length alreadyFlashed' == length alreadyFlashed + then (length alreadyFlashed, state') + else (n, res) + +step state dim = + let state' = incAllBy1 state + (flashesN, state'') = iterateFlashes state' dim [] + in (flashesN, resetFlashed state'') + +e1 :: State -> Dim -> (Int, State) +e1 hmap dim = + foldl' + ( \(n, state) _ -> + let (n', state') = step state dim + in (n + n', state') + ) + (0, hmap) + [1 .. 100] + +e2 :: State -> Dim -> Int +e2 hmap dim@(xsize, ysize) = + foldM + ( \state s -> + let (n', state') = step state dim + in if n' == xsize * ysize + then Left s + else Right state' + ) + hmap + [1 ..] + $> (\(Left s) -> s) + +main :: IO () +main = + do + contents <- getContents + + let input = contents $> lines .> map (map digitToInt) + let dim@(ysize, xsize) = (length input, length (head input)) + let coords = [(x, y) | y <- [0 .. ysize - 1], x <- [0 .. xsize -1]] + let hmap = Map.fromList $ zip coords (concat input) + + e1 hmap dim $> fst .> print + e2 hmap dim $> print diff --git a/day11/simple1.txt b/day11/simple1.txt new file mode 100644 index 0000000..ae21dd2 --- /dev/null +++ b/day11/simple1.txt @@ -0,0 +1,5 @@ +11111 +19991 +19191 +19991 +11111 diff --git a/day11/simple2.txt b/day11/simple2.txt new file mode 100644 index 0000000..02944ac --- /dev/null +++ b/day11/simple2.txt @@ -0,0 +1,5 @@ +00000 +00000 +00900 +00000 +00000 diff --git a/day11/test.txt b/day11/test.txt new file mode 100644 index 0000000..03743f6 --- /dev/null +++ b/day11/test.txt @@ -0,0 +1,10 @@ +5483143223 +2745854711 +5264556173 +6141336146 +6357385478 +4167524645 +2176841721 +6882881134 +4846848554 +5283751526 diff --git a/utils.hs b/utils.hs index 0ba4bcb..740a58f 100644 --- a/utils.hs +++ b/utils.hs @@ -25,4 +25,9 @@ removeAt :: [Int] -> [b] -> [b] removeAt is xs = mapWithIndex id xs $> filter (\(i', _) -> i' `notElem` is) .> map snd slice :: Int -> Int -> [a] -> [a] -slice from to xs = take (to - from + 1) (drop from xs) \ No newline at end of file +slice from to xs = take (to - from + 1) (drop from xs) + +splitEvery _ [] = [] +splitEvery n list = first : splitEvery n rest + where + (first, rest) = splitAt n list \ No newline at end of file -- cgit v1.3