diff --git a/hs/src/Aoc/Y2020.hs b/hs/src/Aoc/Y2020.hs index ddb03fd..d347d1d 100644 --- a/hs/src/Aoc/Y2020.hs +++ b/hs/src/Aoc/Y2020.hs @@ -11,6 +11,7 @@ import qualified Aoc.Y2020.D05 as D05 import qualified Aoc.Y2020.D06 as D06 import qualified Aoc.Y2020.D07 as D07 import qualified Aoc.Y2020.D08 as D08 +import qualified Aoc.Y2020.D09 as D09 year :: Year year = Year 2020 @@ -22,4 +23,5 @@ year = Year 2020 , ( 6, D06.day) , ( 7, D07.day) , ( 8, D08.day) + , ( 9, D09.day) ] diff --git a/hs/src/Aoc/Y2020/D09.hs b/hs/src/Aoc/Y2020/D09.hs new file mode 100644 index 0000000..2ac0ee8 --- /dev/null +++ b/hs/src/Aoc/Y2020/D09.hs @@ -0,0 +1,50 @@ +module Aoc.Y2020.D09 + ( day + ) where + +import Control.Monad +import Data.List + +import Aoc.Day +import Aoc.Parse + +parser :: Parser [Int] +parser = manyLines decimal + +splitAndGroup :: Int -> [Int] -> [([Int], Int)] +splitAndGroup width + = map (\l -> (take width l, l !! width)) + . filter ((> width) . length) + . tails + +isValid :: [Int] -> Int -> Bool +isValid nums n = not $ null $ do + a <- nums + b <- nums + guard $ a /= b + guard $ a + b == n + pure () + +-- Fast enough to give me a result, but not linear time. I couldn't figure out a +-- way to implement the linear time algorithm that didn't look like a mess. +-- Maybe I'll have another go for the cleanup. +findRange :: Int -> [Int] -> [Int] +findRange n + = head + . filter ((== n) . sum) + . map (head . dropWhile ((< n) . sum) . inits) + . tails + +solver :: [Int] -> IO () +solver nums = do + putStrLn ">> Part 1" + let (_, invalidN) = head $ dropWhile (uncurry isValid) $ splitAndGroup 25 nums + print invalidN + + putStrLn "" + putStrLn ">> Part 2" + let weakness = findRange invalidN nums + print $ minimum weakness + maximum weakness + +day :: Day +day = dayParse parser solver