[hs] Shorten 2020_09

Using the plain brute-force approach leads to vastly simpler code at the cost of
some performance. Still pretty fast though.
This commit is contained in:
Joscha 2020-12-09 16:29:25 +00:00
parent 9b34aafbb2
commit f642872ea1

View file

@ -1,15 +1,8 @@
{-# LANGUAGE RecordWildCards #-}
module Aoc.Y2020.D09 module Aoc.Y2020.D09
( day ( day
) where ) where
import Control.Monad
import Data.Foldable
import Data.List import Data.List
import Data.Maybe
import qualified Data.Sequence as Seq
import Aoc.Day import Aoc.Day
import Aoc.Parse import Aoc.Parse
@ -18,32 +11,18 @@ parser :: Parser [Int]
parser = manyLines decimal parser = manyLines decimal
splitAndGroup :: Int -> [Int] -> [([Int], Int)] splitAndGroup :: Int -> [Int] -> [([Int], Int)]
splitAndGroup width splitAndGroup width xs = case splitAt width xs of
= map (\l -> (take width l, l !! width)) (_, []) -> []
. filter ((> width) . length) (as, b:_) -> (as, b) : splitAndGroup width (drop 1 xs)
. tails
isValid :: [Int] -> Int -> Bool isValid :: [Int] -> Int -> Bool
isValid nums n = not $ null $ do isValid nums n = elem n $ (+) <$> nums <*> nums
a <- nums
b <- nums
guard $ a /= b
guard $ a + b == n
pure ()
-- Only works if all numbers are positive. continuousSubsequences :: [a] -> [[a]]
findRange :: Int -> [Int] -> Maybe [Int] continuousSubsequences = filter (not . null) . concatMap tails . inits
findRange target = helper 0 Seq.empty
where findRanges :: Int -> [Int] -> [[Int]]
helper :: Int -> Seq.Seq Int -> [Int] -> Maybe [Int] findRanges target = filter ((== target) . sum) . continuousSubsequences
helper sectionSum section rest = case compare sectionSum target of
EQ -> Just $ toList section
GT -> case Seq.viewl section of
Seq.EmptyL -> Nothing -- Should only happen if sTarget is negative
l Seq.:< ls -> helper (sectionSum - l) ls rest
LT -> case rest of
[] -> Nothing -- Can happen if no sequence of correct sum is found
(r:rs) -> helper (sectionSum + r) (section Seq.|> r) rs
solver :: [Int] -> IO () solver :: [Int] -> IO ()
solver nums = do solver nums = do
@ -53,7 +32,7 @@ solver nums = do
putStrLn "" putStrLn ""
putStrLn ">> Part 2" putStrLn ">> Part 2"
let weakness = fromJust $ findRange invalidN nums let weakness = head $ findRanges invalidN nums
print $ minimum weakness + maximum weakness print $ minimum weakness + maximum weakness
day :: Day day :: Day