2 import Text.ParserCombinators.Parsec.Number
3 import qualified Data.Map.Strict as M
5 data Instruction = Instruction
9 , conditionRegister :: String
14 type Memory = M.Map String Int
19 text <- readFile "data/advent08.txt"
20 let instrs = successfulParse $ parseFile text
25 part1 :: [Instruction] -> Int
26 part1 = largestValue . processInstructions
28 part2 :: [Instruction] -> Int
29 part2 = fst . processInstructionsH
31 processInstructions :: [Instruction] -> Memory
32 processInstructions = foldl processInstruction M.empty
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
44 processInstructionsH :: [Instruction] -> (Int, Memory)
45 processInstructionsH = foldl processInstructionH (0, M.empty)
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
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
62 effectiveChange :: String -> Int -> Int
66 -- effectiveChange "dec" val = -val
69 largestValue :: Memory -> Int
72 | otherwise = maximum $ M.elems m
78 onlySpaces = many (oneOf " \t")
79 symP = (many lower) <* onlySpaces
80 operationP = (many1 (oneOf "!<>=")) <* onlySpaces
82 iFile = iLine `sepBy` newline
83 iLine = instructify <$> symP
86 <*> ( onlySpaces *> string "if" *> onlySpaces *> symP )
89 where instructify r d c cr o p = Instruction { register = r
92 , conditionRegister = cr
97 parseFile :: String -> Either ParseError [Instruction]
98 parseFile input = parse iFile "(unknown)" input
100 parseLine :: String -> Either ParseError Instruction
101 parseLine input = parse iLine "(unknown)" input
103 successfulParse :: Either ParseError [a] -> [a]
104 successfulParse (Left _) = []
105 successfulParse (Right a) = a