Skip to content

Instantly share code, notes, and snippets.

@spellgen
Created December 8, 2020 21:56
Show Gist options
  • Save spellgen/f274172f3f0023e1bb6e9716c7807be9 to your computer and use it in GitHub Desktop.
Save spellgen/f274172f3f0023e1bb6e9716c7807be9 to your computer and use it in GitHub Desktop.
package main
import (
vm "aoc/vm"
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
panic(fmt.Sprintf("usage: %s <input>", os.Args[0]))
}
fh, err := os.Open(os.Args[1])
if err != nil {
panic(err)
}
v0 := vm.NewVM()
err = v0.LoadCode(fh)
if err != nil {
panic(err)
}
// part 1
v1 := v0.Clone()
v1.Run(doneOnInfinite)
fmt.Printf("part 1: accumulator=%d\n", v1.Accumulator())
// part 2
var i2 *vm.Instruction
var v2 *vm.VM
for k, i := range v0.Code() {
switch i.Op {
case "jmp":
i2 = i.Clone()
i2.Op = "nop"
i2.Func = vm.NopFunc
case "nop":
i2 = i.Clone()
i2.Op = "jmp"
i2.Func = vm.JmpFunc
default:
continue
}
v2 = v0.Clone()
err = v2.SetInstruction(k, i2)
if err != nil {
panic(err)
}
v2.Run(doneOnInfinite)
if !v2.IsInfinite() {
break
}
}
switch {
case v2==nil:
fmt.Println("part 2: There were no nop:s or jmp:s in the code")
case v2.IsInfinite():
fmt.Println("part 2: I didn't find any finite execution")
default:
fmt.Printf("part 2: The program exited normally, accumulator=%d\n", v2.Accumulator())
}
}
func doneOnInfinite(v *vm.VM) bool {
return v.IsInfinite()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment