Solve day 3 part 1

This commit is contained in:
George Thomas 2025-12-03 14:39:39 +00:00
parent b99bacc1e3
commit f296e3d5a7
2 changed files with 35 additions and 2 deletions

View File

@ -1,13 +1,45 @@
module Puzzles.Day3 (puzzle) where module Puzzles.Day3 (puzzle) where
import Data.Char (digitToInt)
import Data.Foldable1
import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty, some1)
import Data.List.NonEmpty qualified as NE
import Data.Maybe
import Data.Text qualified as T
import Data.Word
import Puzzle import Puzzle
import Text.Megaparsec
import Text.Megaparsec.Char (digitChar, newline)
puzzle :: Puzzle puzzle :: Puzzle
puzzle = puzzle =
Puzzle Puzzle
{ number = 3 { number = 3
, parser = _ , parser = flip sepEndBy newline $ Bank . fmap (fromIntegral . digitToInt) <$> some1 digitChar
, parts = , parts =
[ _ [ T.show
. sum
. map (digitsToInt . fromMaybe (error "battery list too short") . maxBatteries)
] ]
} }
newtype Bank = Bank (NonEmpty Battery)
deriving newtype (Eq, Ord, Show)
newtype Battery = Battery Word8
deriving newtype (Eq, Ord, Show, Num, Enum, Real, Integral)
-- returns `Nothing` if list isn't long enough (>= 2)
maxBatteries :: Bank -> Maybe (Battery, Battery)
maxBatteries (Bank bs) = do
(b1, i) <- findMax <$> nonEmpty (NE.init bs)
bs' <- nonEmpty $ NE.drop (i + 1) bs
let (b2, _) = findMax bs'
pure (b1, b2)
-- returns the leftmost element in case of a tie
findMax :: (Ord a) => NonEmpty a -> (a, Int)
findMax = foldl1' (\m x -> if fst x > fst m then x else m) . flip NE.zip (0 :| [1 ..])
digitsToInt :: (Battery, Battery) -> Int
digitsToInt (a, b) = fromIntegral $ 10 * a + b

1
outputs/real/3/1 Normal file
View File

@ -0,0 +1 @@
17376