aoc2024/day-17/internal/one/computer.go

109 lines
2.2 KiB
Go
Raw Permalink Normal View History

2024-12-18 15:02:35 +00:00
package one
import (
"math"
)
type computer struct {
registers map[string]int
instructionMap map[int]instructionFn
}
func newComputer(registers map[string]int) *computer {
c := &computer{
registers: registers,
}
c.instructionMap = map[int]instructionFn{
0: c.adv,
1: c.bxl,
2: c.bst,
3: c.jnz,
4: c.bxc,
5: c.out,
6: c.bdv,
7: c.cdv,
}
return c
}
func (c *computer) run(program []int) []int {
results := []int{}
var ptr int
for ptr < len(program) {
opcode := program[ptr]
jump, doJump, out, doStore := c.performOperation(c.instructionMap[opcode], operand(program[ptr+1]))
if doJump {
ptr = jump
} else {
ptr += 2
}
if doStore {
results = append(results, out)
}
}
return results
}
func (c *computer) performOperation(fn instructionFn, operand operand) (int, bool, int, bool) {
return fn(operand)
}
func (c *computer) adv(operand operand) (int, bool, int, bool) {
c.registers["A"] /= int(math.Pow(2, float64(c.combo(operand))))
return 0, false, 0, false
}
func (c *computer) bxl(operand operand) (int, bool, int, bool) {
c.registers["B"] ^= int(operand)
return 0, false, 0, false
}
func (c *computer) bst(operand operand) (int, bool, int, bool) {
c.registers["B"] = c.combo(operand) % 8
return 0, false, 0, false
}
func (c *computer) jnz(operand operand) (int, bool, int, bool) {
if c.registers["A"] == 0 {
return 0, false, 0, false
}
return int(operand), true, 0, false
}
func (c *computer) bxc(operand operand) (int, bool, int, bool) {
c.registers["B"] ^= c.registers["C"]
return 0, false, 0, false
}
func (c *computer) out(operand operand) (int, bool, int, bool) {
return 0, false, c.combo(operand) % 8, true
}
func (c *computer) bdv(operand operand) (int, bool, int, bool) {
c.registers["B"] = c.registers["A"] / int(math.Pow(2, float64(c.combo(operand))))
return 0, false, 0, false
}
func (c *computer) cdv(operand operand) (int, bool, int, bool) {
c.registers["C"] = c.registers["A"] / int(math.Pow(2, float64(c.combo(operand))))
return 0, false, 0, false
}
func (c *computer) combo(operand operand) int {
switch operand {
case 0, 1, 2, 3:
return int(operand)
case 4:
return c.registers["A"]
case 5:
return c.registers["B"]
case 6:
return c.registers["C"]
default:
return 0
}
}