Day 8
[advent-of-code-17.git] / src / advent08 / advent08.hs
1 import Text.Parsec
2 import Text.ParserCombinators.Parsec.Number
3 import qualified Data.Map.Strict as M
4
5 data Instruction = Instruction
6 { register :: String
7 , direction :: String
8 , change :: Int
9 , conditionRegister :: String
10 , operation :: String
11 , comparator :: Int
12 } deriving (Show, Eq)
13
14 type Memory = M.Map String Int
15
16
17 main :: IO ()
18 main = do
19 text <- readFile "data/advent08.txt"
20 let instrs = successfulParse $ parseFile text
21 print $ part1 instrs
22 print $ part2 instrs
23
24
25 part1 :: [Instruction] -> Int
26 part1 = largestValue . processInstructions
27
28 part2 :: [Instruction] -> Int
29 part2 = fst . processInstructionsH
30
31 processInstructions :: [Instruction] -> Memory
32 processInstructions = foldl processInstruction M.empty
33
34 processInstruction :: Memory -> Instruction -> Memory
35 processInstruction memory instruction = memory'
36 where v = M.findWithDefault 0 (register instruction) memory
37 cv = M.findWithDefault 0 (conditionRegister instruction) memory
38 condition = conditionEval cv (operation instruction) (comparator instruction)
39 delta = effectiveChange (direction instruction) (change instruction)
40 memory' = if condition
41 then M.insert (register instruction) (v + delta) memory
42 else memory
43
44 processInstructionsH :: [Instruction] -> (Int, Memory)
45 processInstructionsH = foldl processInstructionH (0, M.empty)
46
47 processInstructionH :: (Int, Memory) -> Instruction -> (Int, Memory)
48 processInstructionH (highest, memory) instruction = (highest', memory')
49 where memory' = processInstruction memory instruction
50 h = largestValue memory'
51 highest' = if h > highest then h else highest
52
53 conditionEval :: Int -> String -> Int -> Bool
54 conditionEval reg op val
55 | op == "==" = reg == val
56 | op == "<" = reg < val
57 | op == ">" = reg > val
58 | op == "<=" = reg <= val
59 | op == ">=" = reg >= val
60 | op == "!=" = reg /= val
61
62 effectiveChange :: String -> Int -> Int
63 effectiveChange d val
64 | d == "inc" = val
65 | otherwise = -val
66 -- effectiveChange "dec" val = -val
67
68
69 largestValue :: Memory -> Int
70 largestValue m
71 | M.null m = 0
72 | otherwise = maximum $ M.elems m
73
74
75
76
77
78 onlySpaces = many (oneOf " \t")
79 symP = (many lower) <* onlySpaces
80 operationP = (many1 (oneOf "!<>=")) <* onlySpaces
81
82 iFile = iLine `sepBy` newline
83 iLine = instructify <$> symP
84 <*> symP
85 <*> int
86 <*> ( onlySpaces *> string "if" *> onlySpaces *> symP )
87 <*> operationP
88 <*> int
89 where instructify r d c cr o p = Instruction { register = r
90 , direction = d
91 , change = c
92 , conditionRegister = cr
93 , operation = o
94 , comparator = p
95 }
96
97 parseFile :: String -> Either ParseError [Instruction]
98 parseFile input = parse iFile "(unknown)" input
99
100 parseLine :: String -> Either ParseError Instruction
101 parseLine input = parse iLine "(unknown)" input
102
103 successfulParse :: Either ParseError [a] -> [a]
104 successfulParse (Left _) = []
105 successfulParse (Right a) = a