Browse Source

feat: solve part 2 day 3

master
Jacob Jonsson 2 days ago
parent
commit
19194b5d78
  1. 3
      aoc25.cabal
  2. 41
      app/Day3.hs

3
aoc25.cabal

@ -67,7 +67,8 @@ executable aoc25
-- other-extensions:
-- Other library packages from which modules are imported.
build-depends: base ^>=4.18.2.1
build-depends: base ^>=4.18.2.1,
containers >= 0.6.7
-- Directories containing source files.
hs-source-dirs: app

41
app/Day3.hs

@ -2,7 +2,9 @@ module Main where
import Data.Char (digitToInt)
import Data.Either (rights)
import Debug.Trace
import Data.List (foldl')
import Data.Map (Map)
import qualified Data.Map as M
import System.Environment (getArgs)
-- | A candidate is either a left-most number we've just selected, or
@ -37,8 +39,43 @@ part1 = sum . map (maximum . map combine . rights . foldl go [] . map digitToInt
combine :: (Int, Int) -> Int
combine (a, b) = a * 10 + b
type CandidateN = [Int]
-- | Maintain one partial candidates for each length.
--
-- Insight: If there are at least N-1 digits left after we've spotted
-- the greatest digit, that digit needs to be the first digit of our
-- candidates.
--
-- Insight 2: We only ever need to store one candidate per length.
part2 :: String -> Int
part2 = error "Not implemented"
part2 = sum . map (combine . (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
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]
-- replaces a candidate with a better one with the same length
insertMaxCandidate :: Map Int CandidateN -> CandidateN -> Map Int CandidateN
insertMaxCandidate m c = M.insertWith maxCandidate (length c) c m
maxCandidate :: CandidateN -> CandidateN -> CandidateN
maxCandidate a b
| combine a > combine b = a
| otherwise = b
combine :: CandidateN -> Int
combine xs = sum $ zipWith power [0 :: Int ..] (reverse xs)
power :: Int -> Int -> Int
power pow b = b * 10 ^ pow
testInput :: String
testInput =

Loading…
Cancel
Save