From c13b852c4ff522fc5ccaf8c39783726c65beee26 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 9 Dec 2019 14:10:51 +0100 Subject: [PATCH] Add 2019 day 5 --- y2019/src/Day5.hs | 113 +++++++++++++++++++++++++++++++++++++++++ y2019/src/DayPicker.hs | 2 + 2 files changed, 115 insertions(+) create mode 100644 y2019/src/Day5.hs diff --git a/y2019/src/Day5.hs b/y2019/src/Day5.hs new file mode 100644 index 0000000..3952974 --- /dev/null +++ b/y2019/src/Day5.hs @@ -0,0 +1,113 @@ +module Day5 (day5, computeOpCode) where + +import Data.List.Split +-- import Debug.Trace +trace _ x = x + +replaceNth :: Int -> a -> [a] -> [a] +replaceNth _ _ [] = [] +replaceNth n newVal (x:xs) + | n == 0 = newVal:xs + | otherwise = x:replaceNth (n-1) newVal xs + +-- computeOpCode: Take an INT and returns a tuple4: +-- - Int = opcode +-- - Subsequent bools = Mode of nth param (True = direct / False = pos mode) +computeOpCode :: Int -> (Int, Bool, Bool, Bool) +computeOpCode input = trace ("ComputeOpCode " ++ show input ++ " -> " ++ show result) result + where opcode = input `mod` 100 + digits = show input + len = length digits + firstParamMode = if len > 2 then (digits !! (len - 3)) == '1' else False + secondParamMode = if len > 3 then (digits !! (len - 4)) == '1' else False + thirdParamMode = if len > 4 then (digits !! (len - 5)) == '1' else False + result = (opcode, firstParamMode, secondParamMode, thirdParamMode) + +getValue :: [Int] -> (Int, Bool) -> Int +getValue _ (n, True) = n +getValue r (n, False) = r !! n + +-- opcode 1 +opcodeAddition :: [Int] -> (Int, Int, Int) -> [Int] +opcodeAddition regs (operand1, operand2, resultIndex) = replaceNth resultIndex result regs + where result = operand1 + operand2 + +-- opcode 2 +opcodeMultiplication :: [Int] -> (Int, Int, Int) -> [Int] +opcodeMultiplication regs (operand1, operand2, resultIndex) = replaceNth resultIndex result regs + where result = operand1 * operand2 + +-- opcode 7 +opcodeLessThan :: [Int] -> (Int, Int, Int) -> [Int] +opcodeLessThan regs (operand1, operand2, resultIndex) = replaceNth resultIndex result regs + where result = if operand1 < operand2 then 1 else 0 + +-- opcode 8 +opcodeEqual :: [Int] -> (Int, Int, Int) -> [Int] +opcodeEqual regs (operand1, operand2, resultIndex) = replaceNth resultIndex result regs + where result = if operand1 == operand2 then 1 else 0 + +processInput :: Int -> [Int] -> [Int] -> Int -> ([Int], [Int]) +processInput inputValue input output index + | opcode == 1 = let newInput = opcodeAddition input (p1, p2, p3) + p1 = getValue' (val1, mode1) + p2 = getValue' (val2, mode2) + p3 = getValue' (val3, True) + newIndex = index + 4 + in trace ("Opcode1 (add) (" ++ show p1 ++ ") + (" ++ show p2 ++ ") -> @" ++ show p3) processInput' newInput output newIndex + | opcode == 2 = let newInput = opcodeMultiplication input (p1, p2, p3) + p1 = getValue' (val1, mode1) + p2 = getValue' (val2, mode2) + p3 = getValue' (val3, True) + newIndex = index + 4 + in trace ("Opcode2 (mult) (" ++ show p1 ++ ") * (" ++ show p2 ++ ") -> @" ++ show p3) (processInput' newInput output newIndex) + | opcode == 3 = let newInput = replaceNth p1 inputValue input + p1 = getValue' (val1, True) + newIndex = index + 2 + in trace ("Opcode3 (read) (1) -> @" ++ show p1) processInput' newInput output newIndex + | opcode == 4 = let newOutput = p1:output + p1 = getValue' (val1, mode1) + newIndex = index + 2 + in trace ("Opcode4 (output) " ++ show p1) processInput' input newOutput newIndex + | opcode == 5 = let p1 = getValue' (val1, mode1) + p2 = getValue' (val2, mode2) + newIndex = if p1 /= 0 then p2 else index + 3 + in trace ("Opcode5 (jump-if-true) " ++ show p1 ++ " != 0 ? -> JMP @" ++ show p2) processInput' input output newIndex + | opcode == 6 = let p1 = getValue' (val1, mode1) + p2 = getValue' (val2, mode2) + newIndex = if p1 == 0 then p2 else index + 3 + in trace ("Opcode6 (jump-if-false) " ++ show p1 ++ " == 0 ? -> JMP @" ++ show p2) processInput' input output newIndex + | opcode == 7 = let p1 = getValue' (val1, mode1) + p2 = getValue' (val2, mode2) + p3 = getValue' (val3, True) + newInput = opcodeLessThan input (p1, p2, p3) + newIndex = index + 4 + in trace ("Opcode7 (less-than) " ++ show p1 ++ " < " ++ show p2 ++ " ? -> @" ++ show p3) processInput' newInput output newIndex + | opcode == 8 = let p1 = getValue' (val1, mode1) + p2 = getValue' (val2, mode2) + p3 = getValue' (val3, True) + newInput = opcodeEqual input (p1, p2, p3) + newIndex = index + 4 + in trace ("Opcode7 (equal) " ++ show p1 ++ " == " ++ show p2 ++ " ? -> @" ++ show p3) processInput' newInput output newIndex + | otherwise = (input, output) + where (opcode, mode1, mode2, mode3) = computeOpCode (input !! index) + getValue' = getValue input + val1 = input !! (index + 1) + val2 = input !! (index + 2) + val3 = input !! (index + 3) + processInput' = processInput inputValue + +day5 :: IO () +day5 = do + putStrLn "AoC 2019 day 5" + putStr "Input >" + input <- getLine + putStrLn "" + + let intCodes = map (read :: String -> Int) (splitOn "," input) + + let (_, outputP1) = processInput 1 intCodes [] 0 + putStrLn ("Part1: " ++ show (outputP1 !! 0)) + + let (_, outputP2) = processInput 5 intCodes [] 0 + putStrLn ("Part2: " ++ show (outputP2 !! 0)) diff --git a/y2019/src/DayPicker.hs b/y2019/src/DayPicker.hs index b0ab92d..287364a 100644 --- a/y2019/src/DayPicker.hs +++ b/y2019/src/DayPicker.hs @@ -9,6 +9,7 @@ import Day1 import Day2 import Day3 import Day4 +import Day5 -- TODO Better way? load :: [String] -> IO () @@ -17,6 +18,7 @@ load ("1":_) = day1 load ("2":_) = day2 load ("3":_) = day3 load ("4":_) = day4 +load ("5":_) = day5 load _ = putStrLn "Unavailable date" dayPicker :: IO ()