From 6723ef2021fb2cf2d7bcd97096b13c71adce203f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Tue, 14 Dec 2021 00:40:52 +0000 Subject: [PATCH] day11: Complete puzzles --- 11/input.txt | 10 ++++++ 11/octoflash.hs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 11/input.txt create mode 100644 11/octoflash.hs diff --git a/11/input.txt b/11/input.txt new file mode 100644 index 0000000..cfbdc33 --- /dev/null +++ b/11/input.txt @@ -0,0 +1,10 @@ +5421451741 +3877321568 +7583273864 +3451717778 +2651615156 +6377167526 +5182852831 +4766856676 +3437187583 +3633371586 diff --git a/11/octoflash.hs b/11/octoflash.hs new file mode 100644 index 0000000..eb16571 --- /dev/null +++ b/11/octoflash.hs @@ -0,0 +1,93 @@ +import Data.Char (digitToInt) + +main :: IO () +main = do + input <- getContents + let + octopodes = (map (map digitToInt) . lines) input + (putStrLn . show . solution1) octopodes + (putStrLn . show . solution2) octopodes + +solution1 :: [[Int]] -> Int +solution1 m = snd (iterate flashSimulate (m, 0) !! 100) + +solution2 :: [[Int]] -> Int +solution2 m = countUntil (all (all (==0)) . fst) flashSimulate (m, 0) + +flashSimulate :: ([[Int]], Int) -> ([[Int]], Int) +flashSimulate (octopodes, flashes) = + (refreshOctopodes exhaustedOctopodes, flashes + countExhaustedOctopodes exhaustedOctopodes) + where + exhaustedOctopodes = flashStep octopodes + countExhaustedOctopodes = foldr (\l a -> length l + a) 0 . map (filter (> 9)) + refreshOctopodes = map (map (\o -> if o > 9 then 0 else o)) + +flashStep :: [[Int]] -> [[Int]] +flashStep = propagateFlashes . map (map (+1)) + where + propagateFlashes :: [[Int]] -> [[Int]] + propagateFlashes = until allExhausted flashOctopi + where + allExhausted :: [[Int]] -> Bool + allExhausted = all (all (/= 10)) + flashOctopi :: [[Int]] -> [[Int]] + flashOctopi m = map (map (incrementFlashing m)) + [[(x, y) | y <- [0..length (m !! x) - 1]] | x <- [0..length m - 1]] + where + incrementFlashing ::[[Int]] -> (Int, Int) -> Int + incrementFlashing m' o + | charge < 10 && newCharge > 10 = 10 -- Ensure we don't miss an increment + | otherwise = charge + numFlashingNeighbors o + where + newCharge = charge + numFlashingNeighbors o + charge = m' !!! o + numFlashingNeighbors :: (Int, Int) -> Int + numFlashingNeighbors = length . filter (\o -> (m !!! o) == 10) . (flip adjacent m) + +(!!!) :: [[Int]] -> (Int, Int) -> Int +(!!!) m index = m !! (fst index) !! (snd index) + +countUntil :: (a -> Bool) -> (a -> a) -> a -> Int +countUntil p f = call + where + call x + | p x = 0 + | otherwise = call (f x) + 1 + +adjacent :: (Int, Int) -> [[Int]] -> [(Int, Int)] +adjacent (x, y) m = [(x+i, y+j) | + i <- [-1..1], + j <- [-1..1], + -- (i, j) /= (0, 0), + x+i >= 0, + y+j >= 0, + x+i < length m, + y+j < length (m !! 0)] + +-- Tests + +testInput1 = [ + "5483143223", + "2745854711", + "5264556173", + "6141336146", + "6357385478", + "4167524645", + "2176841721", + "6882881134", + "4846848554", + "5283751526" + ] +parsedTestInput1 = map (map digitToInt) testInput1 + +testInput2 = [ + "11111", + "19991", + "19191", + "19991", + "11111" + ] +parsedTestInput2 = map (map digitToInt) testInput2 + +test1 = solution1 parsedTestInput1 +test2 = solution2 parsedTestInput1