mirror of
https://github.com/mx42/adventofcode.git
synced 2026-01-14 13:59:51 +01:00
Add 2019 day 5
This commit is contained in:
113
y2019/src/Day5.hs
Normal file
113
y2019/src/Day5.hs
Normal file
@@ -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))
|
||||||
@@ -9,6 +9,7 @@ import Day1
|
|||||||
import Day2
|
import Day2
|
||||||
import Day3
|
import Day3
|
||||||
import Day4
|
import Day4
|
||||||
|
import Day5
|
||||||
|
|
||||||
-- TODO Better way?
|
-- TODO Better way?
|
||||||
load :: [String] -> IO ()
|
load :: [String] -> IO ()
|
||||||
@@ -17,6 +18,7 @@ load ("1":_) = day1
|
|||||||
load ("2":_) = day2
|
load ("2":_) = day2
|
||||||
load ("3":_) = day3
|
load ("3":_) = day3
|
||||||
load ("4":_) = day4
|
load ("4":_) = day4
|
||||||
|
load ("5":_) = day5
|
||||||
load _ = putStrLn "Unavailable date"
|
load _ = putStrLn "Unavailable date"
|
||||||
|
|
||||||
dayPicker :: IO ()
|
dayPicker :: IO ()
|
||||||
|
|||||||
Reference in New Issue
Block a user