In [1]:
inputLine = head . lines <$> readFile "input/day02.txt"
In [2]:
import Data.Array
type Program = Array Int Int
listToProgram :: [Int] -> Program
listToProgram numbers = listArray (0, length numbers - 1) numbers
In [3]:
import Data.List.Split
parseProgram :: String -> Program
parseProgram line = listToProgram . map read . splitOn "," $ line
In [4]:
import Control.Lens
writeTo :: Int -> Int -> Program -> Program
writeTo index newValue program = set (element index) newValue program
In [5]:
executeIndex :: Int -> Program -> Program
executeIndex index program =
case opcode of
99 -> program
1 -> calculate (+)
2 -> calculate (*)
where
numberAtOffset offset = program ! (index + offset)
opcode = numberAtOffset 0
operand number = program ! numberAtOffset number
destinationIndex = numberAtOffset 3
calculate operator = executeIndex (index + 4) modifiedProgram
where
result = operator (operand 1) (operand 2)
modifiedProgram = writeTo destinationIndex result program
executeProgram :: Program -> Program
executeProgram program = executeIndex 0 program
In [6]:
check = elems . executeProgram . listToProgram
In [7]:
check [1,9,10,3,2,3,11,0,99,30,40,50]
In [8]:
check [1,0,0,0,99]
In [9]:
check [2,3,0,3,99]
In [10]:
check [2,4,4,5,99,0]
In [11]:
check [1,1,1,4,99,5,6,0,99]
In [12]:
program = parseProgram <$> inputLine
In [13]:
modifiedProgram = writeTo 1 12 . writeTo 2 2 <$> program
In [14]:
(!0) . executeProgram <$> modifiedProgram
In [15]:
programWithInput :: Int -> Int -> Program -> Program
programWithInput input1 input2 = writeTo 1 input1 . writeTo 2 input2
In [16]:
outputForInput :: Int -> Int -> Program -> Int
outputForInput input1 input2 = (!0) . executeProgram . programWithInput input1 input2
In [17]:
outputForInput 12 2 <$> program
In [18]:
findInputsForOutput :: Int -> Program -> [(Int, Int)]
findInputsForOutput output program = filter yieldsExpectedOutput [(a, b) | a <- [0..99], b <- [0..99]]
where
yieldsExpectedOutput = (==output) . flip (uncurry outputForInput) program
In [19]:
findInputsForOutput 7594646 <$> program
In [20]:
findInputsForOutput 19690720 <$> program
In [21]:
solutionPart2 :: Int -> Program -> Int
solutionPart2 output = uncurry ((+) . (*100)) . head . findInputsForOutput output
solutionPart2 19690720 <$> program