this repo has no description
1module Lib
2 ( processInstructions
3 , findLargestValue
4 , largestEver
5 ) where
6
7import qualified Data.Map.Strict as M
8
9type Instruction = (String, (Int -> Int), String, (Int -> Bool))
10type RegisterMap = M.Map String Int
11
12processInstructions :: [String] -> RegisterMap
13processInstructions strs =
14 let instructions = map parseInstruction strs
15 in foldl updateRegisters (M.singleton "MAX" 0) instructions
16
17findLargestValue :: RegisterMap -> Int
18findLargestValue m = maximum . map snd . M.toList $ m
19
20largestEver :: RegisterMap -> Int
21largestEver m = case M.lookup "MAX" m of
22 Just x -> x
23 Nothing -> 0
24
25updateRegisters :: RegisterMap -> Instruction -> RegisterMap
26updateRegisters m (target, operation, testTarget, test) =
27 let testValue = getRegisterValue testTarget m
28 targetValue = getRegisterValue target m
29 registerMap = if testValue == 0 then M.insert testTarget 0 m else m
30 registerMap' = if targetValue == 0 then M.insert target 0 registerMap else registerMap
31 in if test $ getRegisterValue testTarget registerMap'
32 then let newMap = M.adjust operation target registerMap'
33 in M.adjust (\_ -> findLargestValue newMap) "MAX" newMap
34 else registerMap'
35
36getRegisterValue :: String -> RegisterMap -> Int
37getRegisterValue register m = case M.lookup register m of
38 Just x -> x
39 Nothing -> 0
40
41parseInstruction :: String -> Instruction
42parseInstruction str =
43 let target = head . words $ str
44 testTarget = words str !! 4
45 in (target, parseOperation str, testTarget, parseTest str)
46
47parseOperation :: String -> (Int -> Int)
48parseOperation str =
49 let opStr = head . drop 1 $ words str
50 amt = read (head . drop 2 $ words str) :: Int
51 in case opStr of
52 "inc" -> (+) amt
53 "dec" -> (\x -> x - amt)
54 otherwise -> id
55
56parseTest :: String -> (Int -> Bool)
57parseTest str =
58 let opStr = words str !! 5
59 amt = read (words str !! 6) :: Int
60 in case opStr of
61 "==" -> (== amt)
62 "!=" -> (/= amt)
63 ">" -> (> amt)
64 ">=" -> (>= amt)
65 "<" -> (< amt)
66 "<=" -> (<= amt)
67 otherwise -> (\_ -> False)