2019 Complete!
This commit is contained in:
118
2019/intcode-processor/opt_proc.go
Normal file
118
2019/intcode-processor/opt_proc.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package intcodeprocessor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type OptProc struct {
|
||||
OriginalCode []int
|
||||
Code []int
|
||||
Ptr int
|
||||
RelBase int
|
||||
|
||||
State int
|
||||
Error error
|
||||
|
||||
Pause bool
|
||||
Bail bool
|
||||
WaitingForInput bool
|
||||
WaitingForOutput bool
|
||||
|
||||
Debug bool
|
||||
DebugToFile bool
|
||||
}
|
||||
|
||||
func NewOptProc(prog []int) *OptProc {
|
||||
p := new(OptProc)
|
||||
p.State = RET_OK
|
||||
p.OriginalCode = make([]int, len(prog))
|
||||
max := math.MaxInt16
|
||||
if 2*len(prog) > max {
|
||||
max = 2 * len(prog)
|
||||
}
|
||||
p.Code = make([]int, max)
|
||||
copy(p.OriginalCode, prog)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *OptProc) Run(in <-chan int, out chan<- int) int {
|
||||
p.Ptr = 0
|
||||
p.RelBase = 0
|
||||
copy(p.Code, p.OriginalCode)
|
||||
|
||||
for p.State == RET_OK {
|
||||
ins := fmt.Sprintf("%05d", p.Code[p.Ptr])
|
||||
opcode, _ := strconv.Atoi(ins[3:])
|
||||
arg := func(i int) int {
|
||||
switch ins[3-i] {
|
||||
case '1': // Immediate mode
|
||||
return p.Ptr + i
|
||||
case '2': // Relative mode
|
||||
return p.RelBase + p.Code[p.Ptr+i]
|
||||
default: // 1, position mode
|
||||
return p.Code[p.Ptr+i]
|
||||
}
|
||||
}
|
||||
switch opcode {
|
||||
case OP_ADD:
|
||||
p.Code[arg(3)] = p.Code[arg(1)] + p.Code[arg(2)]
|
||||
p.Ptr = p.Ptr + 4
|
||||
case OP_MLT:
|
||||
p.Code[arg(3)] = p.Code[arg(1)] * p.Code[arg(2)]
|
||||
p.Ptr += 4
|
||||
case OP_INP:
|
||||
p.WaitingForInput = true
|
||||
v := <-in
|
||||
p.WaitingForInput = false
|
||||
p.Code[arg(1)] = v
|
||||
p.Ptr += 2
|
||||
|
||||
case OP_OUT:
|
||||
p.WaitingForOutput = true
|
||||
out <- p.Code[arg(1)]
|
||||
p.WaitingForOutput = false
|
||||
p.Ptr += 2
|
||||
|
||||
case OP_JIT:
|
||||
if p.Code[arg(1)] != 0 {
|
||||
p.Ptr = p.Code[arg(2)]
|
||||
} else {
|
||||
p.Ptr += 3
|
||||
}
|
||||
case OP_JIF:
|
||||
if p.Code[arg(1)] == 0 {
|
||||
p.Ptr = p.Code[arg(2)]
|
||||
} else {
|
||||
p.Ptr += 3
|
||||
}
|
||||
case OP_ILT:
|
||||
if p.Code[arg(1)] < p.Code[arg(2)] {
|
||||
p.Code[arg(3)] = 1
|
||||
} else {
|
||||
p.Code[arg(3)] = 0
|
||||
}
|
||||
p.Ptr += 4
|
||||
case OP_IEQ:
|
||||
if p.Code[arg(1)] == p.Code[arg(2)] {
|
||||
p.Code[arg(3)] = 1
|
||||
} else {
|
||||
p.Code[arg(3)] = 0
|
||||
}
|
||||
p.Ptr += 4
|
||||
case OP_RBS:
|
||||
p.RelBase += p.Code[arg(1)]
|
||||
p.Ptr += 2
|
||||
case OP_EXT:
|
||||
p.State = RET_DONE
|
||||
default:
|
||||
p.State = RET_ERR
|
||||
}
|
||||
}
|
||||
return p.State
|
||||
}
|
||||
|
||||
func (p *OptProc) IsStopped() bool {
|
||||
return p.State != RET_OK
|
||||
}
|
||||
Reference in New Issue
Block a user