mirror of
https://github.com/mx42/adventofcode.git
synced 2026-01-14 05:49:52 +01:00
Add 2019 day 7p1 and day 8
This commit is contained in:
@@ -1,36 +1,9 @@
|
||||
module Day2
|
||||
( day2
|
||||
) where
|
||||
module Day2 (day2) where
|
||||
|
||||
import Data.List.Split
|
||||
|
||||
replaceNth :: Int -> a -> [a] -> [a]
|
||||
replaceNth _ _ [] = []
|
||||
replaceNth n newVal (x:xs)
|
||||
| n == 0 = newVal:xs
|
||||
| otherwise = x:replaceNth (n-1) newVal xs
|
||||
|
||||
processInput :: [Int] -> Int -> [Int]
|
||||
processInput input index
|
||||
| opcode == 1 = let operand1 = input !! (input !! (index + 1))
|
||||
operand2 = input !! (input !! (index + 2))
|
||||
resultIndex = input !! (index + 3)
|
||||
result = operand1 + operand2
|
||||
newInput = replaceNth resultIndex result input
|
||||
in processInput newInput newIndex
|
||||
| opcode == 2 = let operand1 = input !! (input !! (index + 1))
|
||||
operand2 = input !! (input !! (index + 2))
|
||||
resultIndex = input !! (index + 3)
|
||||
result = operand1 * operand2
|
||||
newInput = replaceNth resultIndex result input
|
||||
in processInput newInput newIndex
|
||||
| opcode == 99 = input
|
||||
| opcode > 0 = input
|
||||
where opcode = input !! index
|
||||
newIndex = index + 4
|
||||
import Intcode
|
||||
|
||||
computeVerbNoun :: Int -> Int -> [Int] -> Int
|
||||
computeVerbNoun noun verb input = (processInput newInput 0) !! 0
|
||||
computeVerbNoun noun verb input = (fst (computer [] newInput [] 0)) !! 0
|
||||
where newInput = replaceNth 1 noun . replaceNth 2 verb $ input
|
||||
|
||||
bruteforce :: Int -> Int -> [Int] -> Int -> Int
|
||||
@@ -46,7 +19,7 @@ day2 = do
|
||||
putStr "Enter input >"
|
||||
input <- getLine
|
||||
putStrLn ""
|
||||
let intCodes = map (read :: String -> Int) (splitOn "," input)
|
||||
let intCodes = parseProgram input
|
||||
|
||||
putStr "Part 1: "
|
||||
print (computeVerbNoun 12 2 intCodes)
|
||||
|
||||
@@ -1,101 +1,6 @@
|
||||
module Day5 (day5, computeOpCode) where
|
||||
module Day5 (day5) 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
|
||||
import Intcode
|
||||
|
||||
day5 :: IO ()
|
||||
day5 = do
|
||||
@@ -104,10 +9,10 @@ day5 = do
|
||||
input <- getLine
|
||||
putStrLn ""
|
||||
|
||||
let intCodes = map (read :: String -> Int) (splitOn "," input)
|
||||
let intCodes = parseProgram input
|
||||
|
||||
let (_, outputP1) = processInput 1 intCodes [] 0
|
||||
let (_, outputP1) = computer [1] intCodes [] 0
|
||||
putStrLn ("Part1: " ++ show (outputP1 !! 0))
|
||||
|
||||
let (_, outputP2) = processInput 5 intCodes [] 0
|
||||
let (_, outputP2) = computer [5] intCodes [] 0
|
||||
putStrLn ("Part2: " ++ show (outputP2 !! 0))
|
||||
|
||||
30
y2019/src/Day7.hs
Normal file
30
y2019/src/Day7.hs
Normal file
@@ -0,0 +1,30 @@
|
||||
module Day7 (day7) where
|
||||
|
||||
import Data.List
|
||||
import Intcode
|
||||
|
||||
processProgram :: [Int] -> [Int] -> Int
|
||||
processProgram program inputs = head outputs
|
||||
where (_, outputs) = computer inputs program [] 0
|
||||
|
||||
chainProcesses :: [Int] -> [Int] -> Int -> Int
|
||||
chainProcesses program (phase:phases) signal
|
||||
| null phases = newSignal
|
||||
| otherwise = chainProcesses program phases newSignal
|
||||
where newSignal = processProgram program [phase, signal]
|
||||
|
||||
testCombinations :: [Int] -> [([Int], Int)]
|
||||
testCombinations program = map (\p -> (p, chainProcesses program p 0)) phasesPerm
|
||||
where phasesPerm = permutations [0..4]
|
||||
|
||||
day7 :: IO ()
|
||||
day7 = do
|
||||
putStrLn $ "AoC 2019 day 7"
|
||||
input <- getLine
|
||||
|
||||
let program = parseProgram input
|
||||
let combinations = testCombinations program
|
||||
|
||||
let p1 = maximumBy (\(_, a) (_, b) -> compare a b) combinations
|
||||
|
||||
putStrLn $ "Part 1: " ++ (show p1)
|
||||
44
y2019/src/Day8.hs
Normal file
44
y2019/src/Day8.hs
Normal file
@@ -0,0 +1,44 @@
|
||||
module Day8 (day8) where
|
||||
|
||||
import Data.List.Split
|
||||
import Data.List
|
||||
|
||||
width :: Int
|
||||
width = 25
|
||||
|
||||
height :: Int
|
||||
height = 6
|
||||
|
||||
buildLayers :: String -> Int -> Int -> [[Char]]
|
||||
buildLayers "" _ _ = []
|
||||
buildLayers input w h = front:(buildLayers back w h)
|
||||
where (front, back) = splitAt (w * h) input
|
||||
|
||||
decodeLayers :: [String] -> String
|
||||
decodeLayers layers = foldl decodeLayers' (replicate (width * height) '2') layers
|
||||
where decodeLayers' acc layer = map (\(a, l) -> if a == '2' then l else a) (zip acc layer)
|
||||
|
||||
day8 :: IO ()
|
||||
day8 = do
|
||||
putStrLn $ "AoC 2019 day 8"
|
||||
input <- getLine
|
||||
|
||||
let layers = buildLayers input width height
|
||||
|
||||
let countDigit d = length . (filter (== d))
|
||||
|
||||
let min0layer = minimumBy (\ a b -> (countDigit '0' a) `compare` (countDigit '0' b)) layers
|
||||
|
||||
let p1nbOf1 = countDigit '1' min0layer
|
||||
let p1nbOf2 = countDigit '2' min0layer
|
||||
|
||||
putStrLn $ "Part 1: " ++ (show (p1nbOf1 * p1nbOf2))
|
||||
|
||||
putStrLn "Part 2:"
|
||||
|
||||
let decoded = unlines (chunksOf width (decodeLayers layers))
|
||||
|
||||
let repl '0' = ' '
|
||||
repl '1' = '#'
|
||||
repl c = c
|
||||
in putStrLn $ map repl decoded
|
||||
@@ -11,6 +11,8 @@ import Day3
|
||||
import Day4
|
||||
import Day5
|
||||
import Day6
|
||||
import Day7
|
||||
import Day8
|
||||
|
||||
-- TODO Better way?
|
||||
load :: [String] -> IO ()
|
||||
@@ -21,6 +23,8 @@ load ("3":_) = day3
|
||||
load ("4":_) = day4
|
||||
load ("5":_) = day5
|
||||
load ("6":_) = day6
|
||||
load ("7":_) = day7
|
||||
load ("8":_) = day8
|
||||
load _ = putStrLn "Unavailable date"
|
||||
|
||||
dayPicker :: IO ()
|
||||
|
||||
101
y2019/src/Intcode.hs
Normal file
101
y2019/src/Intcode.hs
Normal file
@@ -0,0 +1,101 @@
|
||||
module Intcode (computer, parseProgram, replaceNth) 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
|
||||
|
||||
computer :: [Int] -> [Int] -> [Int] -> Int -> ([Int], [Int])
|
||||
computer readValues 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) computer readValues 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) (computer readValues newInput output newIndex)
|
||||
| opcode == 3 = let newInput = replaceNth p1 (head readValues) input
|
||||
p1 = getValue' (val1, True)
|
||||
newIndex = index + 2
|
||||
in trace ("Opcode3 (read) (1) -> @" ++ show p1) computer (tail readValues) newInput output newIndex
|
||||
| opcode == 4 = let newOutput = p1:output
|
||||
p1 = getValue' (val1, mode1)
|
||||
newIndex = index + 2
|
||||
in trace ("Opcode4 (output) " ++ show p1) computer readValues 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) computer readValues 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) computer readValues 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) computer readValues 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) computer readValues 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)
|
||||
|
||||
parseProgram :: String -> [Int]
|
||||
parseProgram input = map read (splitOn "," input)
|
||||
Reference in New Issue
Block a user