Add day 8 solution.
This commit is contained in:
parent
1fd91cb343
commit
b0147157f1
101
2020/day08.go
Normal file
101
2020/day08.go
Normal file
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user