{-# Language ImportQualifiedPost, QuasiQuotes #-}
{-|
Module      : Main
Description : Day 6 solution
Copyright   : (c) Eric Mertens, 2019
License     : ISC
Maintainer  : emertens@gmail.com

<https://adventofcode.com/2019/day/6>

-}
module Main (main) where

import Advent
import Control.Applicative
import Data.List
import Data.Map (Map)
import Data.Map qualified as Map

-- | >>> :main
-- 110190
-- 343
main :: IO ()
IO ()
main =
  do inp <- [format|2019 6 (%s%)%s%n)*|]

     let orbits = [([Char], [Char])] -> Map [Char] [Char]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [ ([Char]
y,[Char]
x) | ([Char]
x,[Char]
y) <- [([Char], [Char])]
inp]

     print $ sum [ length (path orbits i) | (_,i) <- inp ]

     let you    = Map [Char] [Char]
orbits Map [Char] [Char] -> [Char] -> [Char]
forall k a. Ord k => Map k a -> k -> a
Map.! [Char]
"YOU"
         san    = Map [Char] [Char]
orbits Map [Char] [Char] -> [Char] -> [Char]
forall k a. Ord k => Map k a -> k -> a
Map.! [Char]
"SAN"
         t1     = Map [Char] [Char] -> [Char] -> [[Char]]
forall a. Ord a => Map a a -> a -> [a]
path Map [Char] [Char]
orbits [Char]
you
         t2     = Map [Char] [Char] -> [Char] -> [[Char]]
forall a. Ord a => Map a a -> a -> [a]
path Map [Char] [Char]
orbits [Char]
san
         common = [[Char]] -> [[Char]] -> [[Char]]
forall a. Eq a => [a] -> [a] -> [a]
intersect [[Char]]
t1 [[Char]]
t2

     print (length t1 + length t2 - 2 * length common)

path :: Ord a => Map a a -> a -> [a]
path :: forall a. Ord a => Map a a -> a -> [a]
path Map a a
m a
i =
  case a -> Map a a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup a
i Map a a
m of
    Maybe a
Nothing -> []
    Just a
j  -> a
i a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Map a a -> a -> [a]
forall a. Ord a => Map a a -> a -> [a]
path Map a a
m a
j