Advent of Code 2019 Repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

43 lines
1.3KB

  1. import System.Environment
  2. import Data.Map.Lazy as Map
  3. import Data.List.Split
  4. import Control.Arrow
  5. import Control.Monad (join)
  6. import Data.Tuple (swap)
  7. import Data.List (unfoldr)
  8. import Data.Function (on)
  9. parse :: String -> (String, String)
  10. parse input = (x,y) where [x,y] = splitOn ")" input
  11. orbits :: [(String, String)] -> Map String [String]
  12. orbits input = fromListWith (++) $ second (:[]) <$> input
  13. totalOrbits :: Map String [String] -> Int
  14. totalOrbits orb = sum checksums
  15. where
  16. checksums = checksum <$> orb
  17. checksum = sum . Prelude.map (maybe 1 (+ 1) . flip Map.lookup checksums)
  18. solveA :: [String] -> Int
  19. solveA input = totalOrbits $ orbits $ Prelude.map parse input
  20. rorbits :: [(String, String)] -> Map String String
  21. rorbits input = Map.fromList $ swap <$> input
  22. dropCommonPrefix :: [String] -> [String] -> ([String], [String])
  23. dropCommonPrefix (x:xs) (y:ys) | x == y = dropCommonPrefix xs ys
  24. dropCommonPrefix xs ys = (xs, ys)
  25. path :: [(String, String)] -> String -> [String]
  26. path orbits = (reverse .) . unfoldr $ fmap (join (,)) . flip Map.lookup (rorbits orbits)
  27. solveB :: [String] -> Int
  28. solveB input = uncurry ((+) `on` length) $ dropCommonPrefix (path parsed "SAN") (path parsed "YOU")
  29. where parsed = Prelude.map parse input
  30. main = do
  31. input <- getArgs
  32. print $ solveA input
  33. print $ solveB input