mirror of
https://github.com/onyx-and-iris/aoc2024.git
synced 2025-01-10 14:50:46 +00:00
109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
|
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
|
||
|
}
|
||
|
}
|