content: -- |
  -- Module      : AOC.Challenge.Day06
  -- License     : BSD3
  --
  -- Stability   : experimental
  -- Portability : non-portable
  --
  -- Day 6.  See "AOC.Solver" for the types used in this module!
  
  module AOC.Challenge.Day06 (
      day06a
    , day06b
    ) where
  
  import           AOC.Solver      ((:~>)(..))
  import           Data.Functor    ((<&>))
  import           Data.List.Split (splitOn)
  import           Data.Map        (Map)
  import qualified Data.Map        as M
  import qualified Data.Set        as S
  
  parseParents :: String -> Map String String
  parseParents str = M.fromList [
        (y, x)
      | ln    <- lines str
      , [x,y] <- [splitOn ")" ln]
      ]
  
  day06a :: Map String String :~> Int
  day06a = MkSol
      { sParse = Just . parseParents
      , sShow  = show
      , sSolve = \parents -> Just $
          let orbits :: Map String Int
              orbits = parents <&> \v ->
                 case M.lookup v orbits of
                   Nothing -> 1
                   Just s  -> s + 1
          in  sum orbits
      }
  
  day06b :: Map String String :~> Int
  day06b = MkSol
      { sParse = Just . parseParents
      , sShow  = show
      , sSolve = \parents -> do
          let orbits :: Map String [String]
              orbits = parents <&> \v ->
                 case M.lookup v orbits of
                   Nothing -> []
                   Just ss -> v:ss
          you <- S.fromList <$> M.lookup "YOU" orbits
          san <- S.fromList <$> M.lookup "SAN" orbits
          let onlyYou = you S.\\ san
              onlySan = san S.\\ you
          pure $ S.size onlyYou + S.size onlySan
      }
  
  