feat: solve day4 part 1

We look at each valid (having coordinates inside the grid) neighbor to
a cell including a paper roll and then see if the neighbor contains a
roll of paper or not. Finally we count the number of rolls, if it is
less than 4 we can pick it.
This commit is contained in:
Jacob Jonsson 2025-12-03 23:12:36 +01:00 committed by Jacob Jonsson
parent 19194b5d78
commit 47259d1697
3 changed files with 208 additions and 6 deletions

View file

@ -39,7 +39,7 @@ part1 = sum . map (maximum . map combine . rights . foldl go [] . map digitToInt
combine :: (Int, Int) -> Int
combine (a, b) = a * 10 + b
type CandidateN = [Int]
type CandidateN = ([Int], Int)
-- | Maintain one partial candidates for each length.
--
@ -49,18 +49,18 @@ type CandidateN = [Int]
--
-- Insight 2: We only ever need to store one candidate per length.
part2 :: String -> Int
part2 = sum . map (combine . (M.! 12) . foldl' checkPotential mempty . map digitToInt) . lines
part2 = sum . map (snd . (M.! 12) . foldl' checkPotential mempty . map digitToInt) . lines
where
checkPotential :: Map Int CandidateN -> Int -> Map Int CandidateN
checkPotential cs x =
let partials = filter ((< 12) . length) $ M.elems cs
partials' = [x] : map (genPartial x) partials
partials' = ([x], x) : map (genPartial x) partials
in foldl' insertMaxCandidate cs $ filter ((<= 12) . length) partials'
-- generates new partials by appending x at candidate or after
-- replacing a shedding smaller digits.
genPartial :: Int -> CandidateN -> CandidateN
genPartial x candidate = candidate ++ [x]
genPartial x (ds, _) = let ds' = ds ++ [x] in (ds', combine ds')
-- replaces a candidate with a better one with the same length
insertMaxCandidate :: Map Int CandidateN -> CandidateN -> Map Int CandidateN
@ -68,10 +68,10 @@ part2 = sum . map (combine . (M.! 12) . foldl' checkPotential mempty . map digit
maxCandidate :: CandidateN -> CandidateN -> CandidateN
maxCandidate a b
| combine a > combine b = a
| snd a > snd b = a
| otherwise = b
combine :: CandidateN -> Int
combine :: [Int] -> Int
combine xs = sum $ zipWith power [0 :: Int ..] (reverse xs)
power :: Int -> Int -> Int