Day 8
[advent-of-code-18.git] / src / advent08 / advent08.hs
1 {-# LANGUAGE OverloadedStrings #-}
2
3 -- import Data.List
4
5 import Data.Text (Text)
6 import qualified Data.Text.IO as TIO
7
8 import Data.Void (Void)
9
10 import Text.Megaparsec
11 import Text.Megaparsec.Char
12 import qualified Text.Megaparsec.Char.Lexer as L
13 import qualified Control.Applicative as CA
14
15
16 data Tree = Node [Tree] [Int] deriving (Eq, Show)
17
18 -- instance Foldable Tree where
19 -- foldMap f (Node (t: ts) m) = f m <> foldMap (foldMap f) ts
20
21 main :: IO ()
22 main = do
23 text <- TIO.readFile "data/advent08.txt"
24 let treeSpec = successfulParse text
25 let (tree, _) = parseTree treeSpec
26 -- print $ foldMap sum tree
27 print $ part1 tree
28 print $ part2 tree
29
30 part1 = sum . metadataOfTree
31
32 part2 = valueOfTree
33
34
35 parseTree (c:m:spec) = (Node children metadata, remainder')
36 where (children, remainder) = parseManyTree c spec
37 metadata = take m remainder
38 remainder' = drop m remainder
39
40 parseManyTree n spec
41 | n == 0 = ([], spec)
42 | otherwise = ((tree:otherTrees), remainder')
43 where (tree, remainder) = parseTree spec
44 (otherTrees, remainder') = parseManyTree (n-1) remainder
45
46 metadataOfTree (Node trees metadata) = metadata ++ (concatMap metadataOfTree trees)
47
48 valueOfTree (Node trees metadata)
49 | null trees = sum metadata
50 | otherwise = sum selectedValues
51 where childValues = map valueOfTree trees
52 selectedValues = map (\v -> childValues!!(v-1)) $ filter (<= (length trees)) metadata
53
54
55 -- Parse the input file
56
57 type Parser = Parsec Void Text
58
59 sc :: Parser ()
60 sc = L.space (skipSome spaceChar) CA.empty CA.empty
61 -- sc = L.space (skipSome (char ' ')) CA.empty CA.empty
62
63 lexeme = L.lexeme sc
64 integer = lexeme L.decimal
65
66 treeFileP = many integer
67
68 successfulParse :: Text -> [Int]
69 successfulParse input =
70 case parse treeFileP "input" input of
71 Left _error -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
72 Right treeSpec -> treeSpec