[hs] Clean up 2020_09
This commit is contained in:
parent
a80b3f70d2
commit
45f5f8a30e
1 changed files with 32 additions and 10 deletions
|
|
@ -1,9 +1,15 @@
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
|
||||||
module Aoc.Y2020.D09
|
module Aoc.Y2020.D09
|
||||||
( day
|
( day
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad
|
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
|
||||||
|
|
@ -25,15 +31,31 @@ isValid nums n = not $ null $ do
|
||||||
guard $ a + b == n
|
guard $ a + b == n
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
-- Fast enough to give me a result, but not linear time. I couldn't figure out a
|
data State = State
|
||||||
-- way to implement the linear time algorithm that didn't look like a mess.
|
{ sTarget :: Int
|
||||||
-- Maybe I'll have another go for the cleanup.
|
, sSeq :: Seq.Seq Int
|
||||||
findRange :: Int -> [Int] -> [Int]
|
, sSum :: Int
|
||||||
findRange n
|
, sRest :: [Int]
|
||||||
= head
|
} deriving (Show)
|
||||||
. filter ((== n) . sum)
|
|
||||||
. map (head . dropWhile ((< n) . sum) . inits)
|
newState :: Int -> [Int] -> State
|
||||||
. tails
|
newState target = State target Seq.empty 0
|
||||||
|
|
||||||
|
step :: State -> Either (Maybe [Int]) State
|
||||||
|
step s@State{..} = case compare sSum sTarget of
|
||||||
|
EQ -> Left $ Just $ toList sSeq
|
||||||
|
GT -> case Seq.viewl sSeq of
|
||||||
|
Seq.EmptyL -> Left Nothing -- Should only happen if sTarget is negative
|
||||||
|
l Seq.:< ls -> Right s{ sSeq = ls, sSum = sSum - l }
|
||||||
|
LT -> case sRest of
|
||||||
|
[] -> Left Nothing -- Can happen if no sequence of correct sum is found
|
||||||
|
(r:rs) -> Right s{ sSeq = sSeq Seq.|> r, sSum = sSum + r, sRest = rs }
|
||||||
|
|
||||||
|
untilLeft :: (b -> Either a b) -> b -> a
|
||||||
|
untilLeft f a = either id (untilLeft f) $ f a
|
||||||
|
|
||||||
|
findRange :: Int -> [Int] -> Maybe [Int]
|
||||||
|
findRange target nums = untilLeft step $ newState target nums
|
||||||
|
|
||||||
solver :: [Int] -> IO ()
|
solver :: [Int] -> IO ()
|
||||||
solver nums = do
|
solver nums = do
|
||||||
|
|
@ -43,7 +65,7 @@ solver nums = do
|
||||||
|
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
putStrLn ">> Part 2"
|
putStrLn ">> Part 2"
|
||||||
let weakness = findRange invalidN nums
|
let weakness = fromJust $ findRange invalidN nums
|
||||||
print $ minimum weakness + maximum weakness
|
print $ minimum weakness + maximum weakness
|
||||||
|
|
||||||
day :: Day
|
day :: Day
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue