102 lines
1.9 KiB
Go
102 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"git.annabunch.es/annabunches/adventofcode/2020/lib/fileutils"
|
|
)
|
|
|
|
type Instruction struct {
|
|
Operation string
|
|
Operand int
|
|
}
|
|
|
|
func parseInstruction(input string) Instruction {
|
|
data := strings.Split(input, " ")
|
|
op := data[0]
|
|
operand, err := strconv.Atoi(strings.TrimPrefix(data[1], "+"))
|
|
if err != nil {
|
|
log.Panicf(err.Error())
|
|
}
|
|
return Instruction{
|
|
Operation: op,
|
|
Operand: operand,
|
|
}
|
|
}
|
|
|
|
func executeInstruction(ins Instruction, ip, acc *int, history map[int]bool) {
|
|
history[*ip] = true
|
|
switch ins.Operation {
|
|
case "acc":
|
|
*acc += ins.Operand
|
|
*ip++
|
|
case "jmp":
|
|
*ip += ins.Operand
|
|
case "nop":
|
|
*ip++
|
|
}
|
|
}
|
|
|
|
func executeProgram(instructions []Instruction) (int, bool) {
|
|
ip := 0
|
|
acc := 0
|
|
history := make(map[int]bool)
|
|
|
|
for ip < len(instructions) {
|
|
if _, found := history[ip]; found {
|
|
// detect infinite loop and return
|
|
return acc, true
|
|
}
|
|
executeInstruction(instructions[ip], &ip, &acc, history)
|
|
}
|
|
|
|
return acc, false
|
|
}
|
|
|
|
func main() {
|
|
step := os.Args[1]
|
|
values := fileutils.InputParserStrings(os.Args[2])
|
|
|
|
instructions := make([]Instruction, 0)
|
|
|
|
for _, line := range values {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
ins := parseInstruction(line)
|
|
instructions = append(instructions, ins)
|
|
}
|
|
|
|
switch step {
|
|
case "1":
|
|
ret, loop := executeProgram(instructions)
|
|
if loop {
|
|
fmt.Println("Loop detected. Last ACC value:", ret)
|
|
}
|
|
|
|
case "2":
|
|
for i, ins := range instructions {
|
|
if ins.Operation == "jmp" || ins.Operation == "nop" {
|
|
newInstructions := make([]Instruction, len(instructions))
|
|
copy(newInstructions, instructions)
|
|
switch ins.Operation {
|
|
case "jmp":
|
|
newInstructions[i].Operation = "nop"
|
|
case "nop":
|
|
newInstructions[i].Operation = "jmp"
|
|
}
|
|
ret, loop := executeProgram(newInstructions)
|
|
|
|
if !loop {
|
|
fmt.Println(ret)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|