2020 Day 8 Complete!
This commit is contained in:
133
2020/day08/program.go
Normal file
133
2020/day08/program.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
const (
|
||||
NOP = iota
|
||||
ACC
|
||||
JMP
|
||||
)
|
||||
|
||||
type Instruction struct {
|
||||
OpCode int
|
||||
Operand int
|
||||
}
|
||||
|
||||
func CompileLine(inp string) Instruction {
|
||||
var ret Instruction
|
||||
pts := strings.Split(inp, " ")
|
||||
|
||||
switch pts[0] {
|
||||
case "nop":
|
||||
ret.OpCode = NOP
|
||||
case "acc":
|
||||
ret.OpCode = ACC
|
||||
case "jmp":
|
||||
ret.OpCode = JMP
|
||||
}
|
||||
ret.Operand = h.Atoi(pts[1])
|
||||
return ret
|
||||
}
|
||||
|
||||
type Program struct {
|
||||
Pointer int
|
||||
Accumulator int
|
||||
Instructions []Instruction
|
||||
Code []string
|
||||
History map[int]int
|
||||
BreakOnLoop bool
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
func NewProgram(inp []string) *Program {
|
||||
p := &Program{
|
||||
Pointer: 0,
|
||||
Accumulator: 0,
|
||||
Code: inp,
|
||||
History: make(map[int]int),
|
||||
BreakOnLoop: true,
|
||||
Verbose: true,
|
||||
}
|
||||
p.Compile()
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Program) Copy() *Program {
|
||||
cp := Program{
|
||||
Pointer: p.Pointer,
|
||||
Accumulator: p.Accumulator,
|
||||
Code: p.Code,
|
||||
History: make(map[int]int),
|
||||
BreakOnLoop: p.BreakOnLoop,
|
||||
Verbose: p.Verbose,
|
||||
}
|
||||
for k, v := range p.History {
|
||||
cp.History[k] = v
|
||||
}
|
||||
cp.Compile()
|
||||
return &cp
|
||||
}
|
||||
|
||||
func (p *Program) Compile() {
|
||||
for k := range p.Code {
|
||||
p.Instructions = append(p.Instructions, CompileLine(p.Code[k]))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Program) Run() int {
|
||||
for p.Pointer < len(p.Instructions) {
|
||||
if p.BreakOnLoop {
|
||||
if _, ok := p.History[p.Pointer]; ok {
|
||||
if p.Verbose {
|
||||
fmt.Printf("Instruction %d repeated. Acc: %d\n", p.Pointer, p.Accumulator)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
p.History[p.Pointer] = p.Accumulator
|
||||
switch p.Instructions[p.Pointer].OpCode {
|
||||
case NOP:
|
||||
p.Pointer++
|
||||
case ACC:
|
||||
p.Accumulator = p.Accumulator + p.Instructions[p.Pointer].Operand
|
||||
p.Pointer++
|
||||
case JMP:
|
||||
p.Pointer = p.Pointer + p.Instructions[p.Pointer].Operand
|
||||
}
|
||||
}
|
||||
if p.Verbose {
|
||||
fmt.Println("Done")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *Program) CountOpCodes(tp ...int) int {
|
||||
var ret int
|
||||
for tpk := range tp {
|
||||
for k := range p.Instructions {
|
||||
if p.Instructions[k].OpCode == tp[tpk] {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *Program) FindNthOp(n int, tp ...int) int {
|
||||
for i := 0; i < len(p.Instructions); i++ {
|
||||
for _, tpv := range tp {
|
||||
if p.Instructions[i].OpCode == tpv {
|
||||
n--
|
||||
}
|
||||
if n == 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
Reference in New Issue
Block a user