mirror of
https://github.com/onyx-and-iris/aoc2024.git
synced 2025-01-10 06:40:47 +00:00
115 lines
2.4 KiB
Go
115 lines
2.4 KiB
Go
package two
|
|
|
|
import (
|
|
"math"
|
|
)
|
|
|
|
type computer struct {
|
|
registers map[string]int64
|
|
instructionMap map[int64]instructionFn
|
|
}
|
|
|
|
func newComputer(registers map[string]int64) *computer {
|
|
c := &computer{
|
|
registers: registers,
|
|
}
|
|
|
|
c.instructionMap = map[int64]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) bumpRegisters(next int64) {
|
|
c.registers["A"] = next
|
|
c.registers["B"] = 0
|
|
c.registers["C"] = 0
|
|
}
|
|
|
|
func (c *computer) run(program []int64) []int64 {
|
|
results := []int64{}
|
|
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, int64, bool) {
|
|
return fn(operand)
|
|
}
|
|
|
|
func (c *computer) adv(operand operand) (int, bool, int64, bool) {
|
|
c.registers["A"] /= int64(math.Pow(2, float64(c.combo(operand))))
|
|
return 0, false, 0, false
|
|
}
|
|
|
|
func (c *computer) bxl(operand operand) (int, bool, int64, bool) {
|
|
c.registers["B"] ^= int64(operand)
|
|
return 0, false, 0, false
|
|
}
|
|
|
|
func (c *computer) bst(operand operand) (int, bool, int64, bool) {
|
|
c.registers["B"] = c.combo(operand) % 8
|
|
return 0, false, 0, false
|
|
}
|
|
|
|
func (c *computer) jnz(operand operand) (int, bool, int64, 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, int64, bool) {
|
|
c.registers["B"] ^= c.registers["C"]
|
|
return 0, false, 0, false
|
|
}
|
|
|
|
func (c *computer) out(operand operand) (int, bool, int64, bool) {
|
|
return 0, false, c.combo(operand) % 8, true
|
|
}
|
|
|
|
func (c *computer) bdv(operand operand) (int, bool, int64, bool) {
|
|
c.registers["B"] = c.registers["A"] / int64(math.Pow(2, float64(c.combo(operand))))
|
|
return 0, false, 0, false
|
|
}
|
|
|
|
func (c *computer) cdv(operand operand) (int, bool, int64, bool) {
|
|
c.registers["C"] = c.registers["A"] / int64(math.Pow(2, float64(c.combo(operand))))
|
|
return 0, false, 0, false
|
|
}
|
|
|
|
func (c *computer) combo(operand operand) int64 {
|
|
switch operand {
|
|
case 0, 1, 2, 3:
|
|
return int64(operand)
|
|
case 4:
|
|
return int64(c.registers["A"])
|
|
case 5:
|
|
return int64(c.registers["B"])
|
|
case 6:
|
|
return int64(c.registers["C"])
|
|
default:
|
|
return 0
|
|
}
|
|
}
|