123 lines
1.8 KiB
Go
123 lines
1.8 KiB
Go
package intcodeprocessor
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
OP_ADD = 1
|
|
OP_MLT = 2
|
|
OP_EXT = 99
|
|
)
|
|
|
|
const (
|
|
RET_ERR = iota - 1
|
|
RET_OK
|
|
RET_DONE
|
|
)
|
|
|
|
type Program struct {
|
|
code []int
|
|
ptr int
|
|
|
|
state int
|
|
error error
|
|
}
|
|
|
|
func NewProgram(prog []int) *Program {
|
|
p := new(Program)
|
|
p.code = make([]int, len(prog))
|
|
copy(p.code, prog)
|
|
return p
|
|
}
|
|
|
|
func (p *Program) GetCode() []int {
|
|
return p.code
|
|
}
|
|
|
|
func (p *Program) State() int {
|
|
return p.state
|
|
}
|
|
|
|
func (p *Program) Error() error {
|
|
return p.error
|
|
}
|
|
|
|
func (p *Program) Run() int {
|
|
for {
|
|
p.state = p.Step()
|
|
if p.state != RET_OK {
|
|
return p.state
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *Program) Step() int {
|
|
if len(p.code) < p.ptr {
|
|
p.error = errors.New("Pointer Exception")
|
|
return RET_ERR
|
|
}
|
|
switch p.readNext() {
|
|
case OP_ADD:
|
|
p.add(p.readNextThree())
|
|
if p.error != nil {
|
|
return RET_ERR
|
|
}
|
|
return RET_OK
|
|
case OP_MLT:
|
|
p.mult(p.readNextThree())
|
|
if p.error != nil {
|
|
return RET_ERR
|
|
}
|
|
return RET_OK
|
|
case OP_EXT:
|
|
return RET_DONE
|
|
}
|
|
return RET_ERR
|
|
}
|
|
|
|
func (p *Program) GetProgramValueAt(idx int) int {
|
|
return p.code[idx]
|
|
}
|
|
|
|
func (p *Program) SetProgramValueAt(idx, val int) {
|
|
p.code[idx] = val
|
|
}
|
|
|
|
func (p *Program) readNext() int {
|
|
if len(p.code) <= p.ptr {
|
|
p.error = errors.New("Pointer Exception")
|
|
}
|
|
p.ptr++
|
|
return p.code[p.ptr-1]
|
|
}
|
|
|
|
func (p *Program) readNextTwo() (int, int) {
|
|
return p.readNext(), p.readNext()
|
|
}
|
|
|
|
func (p *Program) readNextThree() (int, int, int) {
|
|
return p.readNext(), p.readNext(), p.readNext()
|
|
}
|
|
|
|
func (p *Program) add(a1, a2, dest int) {
|
|
p.code[dest] = p.code[a1] + p.code[a2]
|
|
}
|
|
|
|
func (p *Program) mult(a1, a2, dest int) {
|
|
p.code[dest] = p.code[a1] * p.code[a2]
|
|
}
|
|
|
|
func (p Program) String() string {
|
|
var ret string
|
|
for k := range p.code {
|
|
if k == p.ptr {
|
|
ret = fmt.Sprintf("%s [%d]", ret, p.code[k])
|
|
} else {
|
|
ret = fmt.Sprintf("%s %d", ret, p.code[k])
|
|
}
|
|
}
|
|
return ret
|
|
}
|