feat: solve part 2 day 3
This commit is contained in:
parent
249365968a
commit
19194b5d78
2 changed files with 41 additions and 3 deletions
41
app/Day3.hs
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…
Add table
Add a link
Reference in a new issue