feat: solve part 2 day 3
This commit is contained in:
parent
249365968a
commit
19194b5d78
2 changed files with 41 additions and 3 deletions
|
|
@ -67,7 +67,8 @@ executable aoc25
|
||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
|
|
||||||
-- Other library packages from which modules are imported.
|
-- 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.
|
-- Directories containing source files.
|
||||||
hs-source-dirs: app
|
hs-source-dirs: app
|
||||||
|
|
|
||||||
41
app/Day3.hs
41
app/Day3.hs
|
|
@ -2,7 +2,9 @@ module Main where
|
||||||
|
|
||||||
import Data.Char (digitToInt)
|
import Data.Char (digitToInt)
|
||||||
import Data.Either (rights)
|
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)
|
import System.Environment (getArgs)
|
||||||
|
|
||||||
-- | A candidate is either a left-most number we've just selected, or
|
-- | 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 :: (Int, Int) -> Int
|
||||||
combine (a, b) = a * 10 + b
|
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 :: 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 :: String
|
||||||
testInput =
|
testInput =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue