Advent of Code 2019, Day 5
Today's advent of code challenge was an extension of day 2
The first part was pretty straightforward; to support addressing modes I wrote a dumb little function to get the arguments:
var argCount = map[int]int{
opAdd: 2,
opMul: 2,
opInput: 0,
opOutput: 1,
opJT: 2,
opJF: 2,
opLT: 2,
opEQ: 2,
opHalt: 0,
}
func fetchArgs(mem []int, ip, params, count int) []int {
if count == 0 {
return nil
}
args := make([]int, 0, count)
for i := 1; i <= count; i++ {
arg := mem[ip+i]
if params%10 == 0 {
arg = mem[arg]
}
params /= 10
args = append(args, arg)
}
return args
}
The intcode Run function now takes an additional parameter (an io.Reader), and the run loop now looks like this:
for run {
op := mem[ip] % 100
params := mem[ip] / 100
args := fetchArgs(mem, ip, params, argCount[op%100])
switch op % 100 {
case opAdd:
dest := mem[ip+3]
mem[dest] = args[0] + args[1]
ip += 4
case opMul:
dest := mem[ip+3]
mem[dest] = args[0] * args[1]
ip += 4
case opInput:
fmt.Printf("? ")
var arg int
fmt.Fscan(r, &arg)
dest := mem[ip+1]
mem[dest] = arg
ip += 2
case opOutput:
fmt.Printf("%08d: %d\n", mem[ip+1], args[0])
ip += 2
case opJT:
if args[0] != 0 {
ip = args[1]
} else {
ip += 3
}
case opJF:
if args[0] == 0 {
ip = args[1]
} else {
ip += 3
}
case opLT:
dest := mem[ip+3]
if args[0] < args[1] {
mem[dest] = 1
} else {
mem[dest] = 0
}
ip += 4
case opEQ:
dest := mem[ip+3]
if args[0] == args[1] {
mem[dest] = 1
} else {
mem[dest] = 0
}
ip += 4
case opHalt:
run = false
default:
return mem, fmt.Errorf("VM: invalid opcode %d [ip=%d]", op, ip)
}
}
I made the choice to use an io.Reader (and really I should convert it to an io.Writer too) so that I could "automate" entering the program.
A few things tripped me up:
- I briefly forgot to update the ip in the jump statements when in the else clause;
- I got the ip increment counter wrong (I'd had it as 2 instead of 3)
- I was treating the output call as an indirect address (position mode) instead of immediate mode, which is how it should have been.
Finally, some stats - my instrumentation output:
2019/12/05 19:36:29 day05p1: complete in 350us, total allocated 75 kB,
current heap allocation 75 kB
2019/12/05 19:36:29 day05p2: complete in 29us, total allocated 83 kB,
current heap allocation 83 kB
And I'll note this was a 245 LOC diff, mostly in the ic package (+165 lines).
I really enjoyed today's challenge, but it's also not the first VM I've written --- I really enjoy writing VMs.
Tags:
advent-of-code,
journal