package main import ( "fmt" "io/ioutil" "log" "os" "strconv" "strings" ) type OpType int const ( OpAdd OpType = 1 OpMul = 2 OpEnd = 99 ) func ExecuteProgram(ops []int) ([]int, error) { for i := 0; i < len(ops); i += 4 { op := OpType(ops[i]) if op == OpEnd { break } if i+3 >= len(ops) { return nil, fmt.Errorf("broken input, could not index: %d", i+3) } a := ops[i+1] b := ops[i+2] out := ops[i+3] if a >= len(ops) { return nil, fmt.Errorf("attempt to index invalid out position: %d", a) } if b >= len(ops) { return nil, fmt.Errorf("attempt to index invalid out position: %d", b) } if out >= len(ops) { return nil, fmt.Errorf("attempt to index invalid out position: %d", out) } switch op { case OpAdd: ops[out] = ops[a] + ops[b] case OpMul: ops[out] = ops[a] * ops[b] default: return nil, fmt.Errorf("invalid op: %d", op) } } return ops, nil } func Run(ops []int, noun, verb int) (int, error) { cOps := make([]int, len(ops)) copy(cOps, ops) cOps[1] = noun cOps[2] = verb result, err := ExecuteProgram(cOps) if err != nil { return 0, fmt.Errorf("could not execute program: %w", err) } return result[0], nil } func main() { input, err := os.Open("input.txt") if err != nil { log.Fatal(fmt.Errorf("could not open input file: %w", err)) } defer input.Close() raw, err := ioutil.ReadAll(input) if err != nil { log.Fatal(fmt.Errorf("error while reading input: %w", err)) } ops, err := func(val []byte) ([]int, error) { vals := strings.Split(strings.TrimSpace(string(val)), ",") result := make([]int, len(vals)) for i := range vals { result[i], err = strconv.Atoi(vals[i]) if err != nil { return nil, fmt.Errorf("could not convert to int: %w", err) } } return result, nil }(raw) if err != nil { log.Fatal(fmt.Errorf("could not read ops: %w", err)) } // Part 1 result, err := Run(ops, 12, 2) if err != nil { log.Fatal(fmt.Errorf("could not run part 1: %w", err)) } fmt.Printf("Part 1, %d\n", result) // Part 2 for noun := 0; noun < 100; noun++ { for verb := 0; verb < 100; verb++ { result, err := Run(ops, noun, verb) if err != nil { log.Fatal(fmt.Errorf("could not run part 2: %w", err)) } if result == 19690720 { fmt.Printf("Part 2, %d\n", (noun*100)+verb) return } } } }