package main
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
"strings"
)
func main() {
if err := realMain(); err != nil {
log.Println(err)
}
}
func realMain() error {
data, err := parseInput()
if err != nil {
return err
}
accumulator, _, err := readCode(data)
if err != nil {
return err
}
log.Println(accumulator)
accumulator2, err := fixCode(data)
if err != nil {
return err
}
log.Println(accumulator2)
return nil
}
func readCode(data []string) (int, int, error) {
visited := map[int]bool{}
var acc int
for i := 0; ; {
if visited[i] {
return acc, i, nil
}
if i >= len(data) {
return acc, i, nil
}
visited[i] = true
line := strings.Split(data[i], " ")
switch line[0] {
case "nop":
i++
case "jmp":
tmp, err := strconv.Atoi(line[1])
if err != nil {
return 0, 0, err
}
i += tmp
case "acc":
tmp, err := strconv.Atoi(line[1])
if err != nil {
return 0, 0, err
}
acc += tmp
i++
default:
return 0, 0, fmt.Errorf("unrecognized instruction")
}
}
}
func fixCode(data []string) (int, error) {
for i := range data {
line := strings.Split(data[i], " ")
var l string
switch line[0] {
case "jmp":
l = "nop " + line[1]
case "nop":
l = "jmp " + line[1]
default:
continue
}
newdata := make([]string, len(data))
copy(newdata, data)
newdata[i] = l
acc, last, err := readCode(newdata)
if err != nil {
return 0, err
}
if last == len(data) {
return acc, nil
}
}
return 0, fmt.Errorf("solution not found")
}
func parseInput() ([]string, error) {
fd, err := os.Open("input.txt")
if err != nil {
return nil, err
}
defer fd.Close()
ret := []string{}
buf := bufio.NewScanner(fd)
for buf.Scan() {
ret = append(ret, buf.Text())
}
return ret, nil
}