Solve day 8 part 2

This commit is contained in:
George Thomas 2025-12-08 23:38:48 +00:00
parent 1e9e70fe10
commit 832b85fb7b
4 changed files with 26 additions and 8 deletions

View File

@ -34,6 +34,8 @@ module Pre (
module Text.Megaparsec.Char, module Text.Megaparsec.Char,
module Text.Megaparsec.Char.Lexer, module Text.Megaparsec.Char.Lexer,
Puzzle (..), Puzzle (..),
digit,
digitsToInt,
) )
where where
@ -61,7 +63,7 @@ import Data.Foldable1
import Data.Function import Data.Function
import Data.Functor import Data.Functor
import Data.List (sortOn, tails, transpose) import Data.List (sortOn, tails, transpose)
import Data.List.Extra (dropEnd, enumerate) import Data.List.Extra (dropEnd, enumerate, notNull, splitOn)
import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty, some1) import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty, some1)
import Data.Maybe import Data.Maybe
import Data.Ord import Data.Ord
@ -88,3 +90,9 @@ data Puzzle = forall input. Puzzle
, parts :: [input -> TL.Text] , parts :: [input -> TL.Text]
, extraTests :: Bool -> FilePath -> IO input -> [TestTree] , extraTests :: Bool -> FilePath -> IO input -> [TestTree]
} }
digit :: (Token s ~ Char, Num b, MonadParsec e s f) => f b
digit = fromIntegral . digitToInt <$> digitChar
digitsToInt :: (Integral a) => [a] -> Int
digitsToInt = snd . foldr (\b (p, acc) -> (10 * p, acc + fromIntegral b * p)) (1, 0)

View File

@ -9,7 +9,7 @@ puzzle :: Puzzle
puzzle = puzzle =
Puzzle Puzzle
{ number = 3 { number = 3
, parser = const $ flip sepEndBy newline $ Bank . fmap (fromIntegral . digitToInt) <$> some1 digitChar , parser = const $ flip sepEndBy newline $ Bank <$> some1 digit
, parts = , parts =
[ TL.show [ TL.show
. sum . sum
@ -39,6 +39,3 @@ maxBatteries n0 (Bank bs0) = flip unfoldrM (n0, toList bs0) \case
-- returns the leftmost element in case of a tie -- returns the leftmost element in case of a tie
findMax :: (Ord a) => NonEmpty a -> (a, Int) 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 ..]) findMax = foldl1' (\m x -> if fst x > fst m then x else m) . flip NE.zip (0 :| [1 ..])
digitsToInt :: [Battery] -> Int
digitsToInt = snd . foldr (\b (p, acc) -> (10 * p, acc + fromIntegral b * p)) (1, 0)

View File

@ -9,14 +9,24 @@ puzzle =
Puzzle Puzzle
{ number = 6 { number = 6
, parser = const do , parser = const do
ints <- (hspace *> (decimal `sepBy1` hspace1)) `sepEndBy1` newline ints <- some ((Just <$> digit) <|> (single ' ' $> Nothing)) `sepEndBy1` newline
ops <- ((single '*' $> Multiply) <|> (single '+' $> Add)) `sepEndBy` hspace1 ops <- ((single '*' $> Multiply) <|> (single '+' $> Add)) `sepEndBy` hspace1
void newline void newline
pure (ops, transpose ints) pure (ops, ints)
, parts = , parts =
[ TL.show [ TL.show
. sum . sum
. uncurry (zipWith \op -> foldl' (apply op) (unit op)) . uncurry (zipWith applyToList)
. second (transpose . map (map (digitsToInt @Int . catMaybes) . filter notNull . splitOn [Nothing]))
, TL.show
. sum
. uncurry (zipWith applyToList)
. second
( map catMaybes
. splitOn [Nothing]
. map (\l -> if all isNothing l then Nothing else Just $ digitsToInt @Int $ catMaybes l)
. transpose
)
] ]
, extraTests = mempty , extraTests = mempty
} }
@ -31,3 +41,5 @@ unit :: Op -> Int
unit = \case unit = \case
Add -> 0 Add -> 0
Multiply -> 1 Multiply -> 1
applyToList :: Op -> [Int] -> Int
applyToList op = foldl' (apply op) (unit op)

1
outputs/real/6/2 Normal file
View File

@ -0,0 +1 @@
11708563470209