-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day6.hs
56 lines (47 loc) · 1.89 KB
/
Day6.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
module Day6
( part1
, part2
) where
import Control.Monad (void)
import Data.Either (Either (Right), isLeft)
import Data.Graph.Inductive.Graph (labNodes)
import Data.Graph.Inductive.PatriciaTree (Gr)
import Data.Graph.Inductive.Query.BFS (esp, level)
import Helpers.Graph (assocsToDigraph)
import Helpers.Parsers (Parser)
import Text.Megaparsec (many, optional, parse,
takeWhile1P)
import Text.Megaparsec.Char (char, eol, letterChar)
type Orbits = Gr String Int
parseOrbits :: Parser Orbits
parseOrbits = assocsToDigraph <$> many parseLine
parseLine :: Parser (String, [(String, Int)])
parseLine = do
n1 <- takeWhile1P Nothing (/= ')')
void . char $ ')'
n2 <- takeWhile1P Nothing (/= '\n')
void . optional $ eol
return (n1, [(n2, 1)])
buildGraph :: String -> Orbits
buildGraph input
| isLeft parsed = error ("couldn't parse " ++ show parsed)
| otherwise = jParsed
where
parsed = parse parseOrbits "" input
(Right jParsed) = parsed
findOrbits :: Orbits -> Int
findOrbits orbits = sum . map snd . level com $ orbits
where
com = fst . head . filter (\x -> snd x == "COM") . labNodes $ orbits
-- we need to remove 3 because we are not counting the first and the last jumps,
-- and we are counting edges and not nodes.
shortPathToSanta :: Orbits -> Int
shortPathToSanta orbits = (-3 +) . length . esp you santa $ orbits
where
you = fst . head . filter (\x -> snd x == "YOU") $ nodes
santa = fst . head . filter (\x -> snd x == "SAN") $ nodes
nodes = labNodes orbits
part1 :: Bool -> String -> String
part1 _ = show . findOrbits . buildGraph
part2 :: Bool -> String -> String
part2 _ = show . shortPathToSanta . buildGraph