This is my solution for Day 2 of Advent of Code 2019.
It's the eval
function I want to get reviewed. Is this acceptable Haskell code? Is it even close to being idiomatic? Also, is it OK to leverage laziness this way?
module Day2 where
import Data.Vector (Vector, fromList, head, (!), (//))
import Data.List.Split (splitOn)
type Intcode = Vector Int
data Op = Add | Mult | Noop
intToOp :: Int -> Op
intToOp 1 = Add
intToOp 2 = Mult
intToOp 99 = Noop
intToOp x = error $ "invalid opCode, should not happen" ++ show x
eval :: Intcode -> Intcode
eval intcode = go intcode 0
where
go intcode currentIndex =
let
op = intToOp $ intcode ! currentIndex
v1Pos = intcode ! (currentIndex + 1)
v2Pos = intcode ! (currentIndex + 2)
savePos = intcode ! (currentIndex + 3)
nextIndex = currentIndex + 4
v1 = intcode ! v1Pos
v2 = intcode ! v2Pos
in
case op of
Add -> go (intcode // [(savePos, (v1 + v2))]) nextIndex
Mult -> go (intcode // [(savePos, (v1 * v2))]) nextIndex
Noop -> intcode
part1 :: IO ()
part1 = do
input <- readFile "../input/day2.txt"
let intcode = fromList (read <$> splitOn "," input)
let result = eval $ intcode // [(1, 12), (2, 2)]
putStrLn $ show $ result ! 0
part2 :: IO ()
part2 = do
input <- readFile "../input/day2.txt"
let memory = fromList (read <$> splitOn "," input)
let inputs = [(i, j) | i <- [0..99], j <- [0..99]]
let results = fmap (\(noun, verb) -> (eval $ memory // [(1, noun), (2, verb)], noun, verb)) inputs
let (result, noun, verb) = Prelude.head $ filter (\(res, _, _) -> (res ! 0) == 19690720) results
putStrLn $ show $ 100 * noun + verb