package main import ( "fmt" "log" "os" "strconv" "strings" "git.annabunch.es/annabunches/adventofcode/2020/lib/util" ) 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 := util.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 } } } } }