Intcode Prep day 1 - Lets get started
Created on Sunday, November 23, 2025.
Intcode Day 1
Ok, I've done the intcode puzzles in previous years, so unlike last time where I was solving each as they come, I know that I'm going to want to model a simple processor with a fetch-execute cycle, a program counter, and a box of memory. In rust this is going to be slightly tricky since mutable state is not normally a thing, or at least an explict thing, but I'm going to try anyway.
We're going to try to start by modeling the memory. I suspect we start with a mutable array that is the length of the opcode entries.
We're then going to want a simple IntCode computer, which has a program counter, and has an execute function which executes the next instruction at the current PC. We're also going to need a mutable state of "running" which opcode 99 sets to false, so we can tell from outside whether the program has halted.
So that looks a bit like this:
pub struct IntCodeCPU {
pub memory: Vec<u32>,
pub pc: usize,
pub running: bool,
}
We then need to handle each of the op codes.
Firstly, the addition opcode needs to get the number from location pc+1 and the location from pc+2 and then get the memory values from each, and add them together and put them into the location stored in pc+3.
let src1 = self.memory[self.memory[self.pc + 1] as usize] as u32;
let src2 = self.memory[self.memory[self.pc + 2] as usize] as u32;
let dest = self.memory[self.pc + 3] as usize;
self.memory[dest] = src1 + src2;
self.pc += 4;
The multiply opcode does the same thing, but multiplies
let src1 = self.memory[self.memory[self.pc + 1] as usize] as u32;
let src2 = self.memory[self.memory[self.pc + 2] as usize] as u32;
let dest = self.memory[self.pc + 3] as usize;
self.memory[dest] = src1 * src2;
self.pc += 4;
Finally, we use a match to handle the op codes, so 1 is add, 2 is mul, and 99 just sets running to 0
let opcode = self.memory[self.pc];
match opcode {
1 => {
let src1 = self.memory[self.memory[self.pc + 1] as usize] as u32;
let src2 = self.memory[self.memory[self.pc + 2] as usize] as u32;
let dest = self.memory[self.pc + 3] as usize;
self.memory[dest] = src1 + src2;
self.pc += 4;
}
2 => {
let src1 = self.memory[self.memory[self.pc + 1] as usize] as u32;
let src2 = self.memory[self.memory[self.pc + 2] as usize] as u32;
let dest = self.memory[self.pc + 3] as usize;
self.memory[dest] = src1 * src2;
self.pc += 4;
}
99 => {
self.running = false;
}
_ => {
panic!("Unknown opcode: {}", opcode);
}
}
To solve part1, we need to remember the instruction to set position 1 to 12 and position 2 is 2 (which obviously changes the first two parameters of the first opcode). That's a bit weird compared to almost every other test we will do, so we move our normal test as if the main is inlined, and then my calculate_part1 will do the modification.
Running that works, so that's looking great!
Part 2
Oh, I had forgotten this. In this case, we don't have to add different op codes, we just need to run the computer to completion over and over again, 9801 times (how handy that the system told us what 99 times 99 was).
This shouldn't be too hard, we just need to remember to clone the input into each run of the computer so that when we reset, we can reset any changes to memory state.
for noun in 0..100 {
for verb in 0..100 {
let mut program = parse_input(_input);
program[1] = noun;
program[2] = verb;
let mut cpu = IntCodeCPU::new(program);
cpu.run();
if cpu.memory[0] == 19690720 {
return (noun * 100 + verb) as usize;
}
}
}
That works, simples, so we can move onto day 5 for intcode problem 2
Next
Previous