module AOC.Challenge.Day03 (
day03a
, day03b
) where
import AOC.Common (Point, mannDist, Dir, dirPoint, parseDir)
import AOC.Solver ((:~>)(..))
import Control.Monad ((<=<))
import Data.List.NonEmpty (NonEmpty(..))
import Data.List.Split (splitOn)
import Data.Map (Map)
import Data.Semigroup (Min(..))
import Safe (scanl1Def)
import Safe.Foldable (minimumMay)
import Text.Read (readMaybe)
import qualified Data.List.NonEmpty as NE
import qualified Data.Map as M
type Path = [(Dir, Int)]
parsePath :: String -> Maybe Path
parsePath = traverse parsePoint . splitOn ","
where
parsePoint (d:ns) = (,) <$> parseDir d <*> readMaybe ns
parsePoint _ = Nothing
crossings :: NonEmpty Path -> Map Point Int
crossings = foldr1 (M.intersectionWith (+)) . fmap follow
where
follow :: Path -> Map Point Int
follow = M.fromListWith min
. flip zip [1..]
. scanl1Def [] (+)
. concatMap (uncurry expandDir)
expandDir d ns = replicate ns (dirPoint d)
day03a :: NonEmpty Path :~> Int
day03a = MkSol
{ sParse = NE.nonEmpty <=< traverse parsePath . lines
, sShow = show
, sSolve = fmap getMin
. foldMap (Just . Min . mannDist 0)
. M.keys
. crossings
}
day03b :: NonEmpty Path :~> Int
day03b = MkSol
{ sParse = NE.nonEmpty <=< traverse parsePath . lines
, sShow = show
, sSolve = minimumMay . crossings
}