diff --git a/2020/day08.go b/2020/day08.go new file mode 100644 index 0000000..58929bd --- /dev/null +++ b/2020/day08.go @@ -0,0 +1,101 @@ +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 + } + } + } + } +}