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 }