From 9b67f2728c0ff2533e56c937dd2866941b6c8fd2 Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Mon, 2 Dec 2019 19:20:52 +0100 Subject: [PATCH] Add solution for Day 2 Signed-off-by: Knut Ahlers --- day02.go | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ day02_input.txt | 1 + day02_test.go | 47 +++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 day02.go create mode 100644 day02_input.txt create mode 100644 day02_test.go diff --git a/day02.go b/day02.go new file mode 100644 index 0000000..3a67245 --- /dev/null +++ b/day02.go @@ -0,0 +1,121 @@ +package aoc2019 + +import ( + "io/ioutil" + "strconv" + "strings" + + "github.com/pkg/errors" +) + +func parseDay02Intcode(code string) ([]int, error) { + parts := strings.Split(code, ",") + + var out []int + for _, n := range parts { + v, err := strconv.Atoi(n) + if err != nil { + return nil, err + } + out = append(out, v) + } + + return out, nil +} + +func executeDay02Intcode(code []int) ([]int, error) { + var ( + pos int + run = true + ) + + for run { + if pos >= len(code) { + return nil, errors.Errorf("Code position out of bounds: %d (len=%d)", pos, len(code)) + } + + switch code[pos] { + case 1: + // addition + p1, p2, pt := code[pos+1], code[pos+2], code[pos+3] + code[pt] = code[p1] + code[p2] + + case 2: + // multiplication + p1, p2, pt := code[pos+1], code[pos+2], code[pos+3] + code[pt] = code[p1] * code[p2] + + case 99: + // program finished + run = false + + default: + return nil, errors.Errorf("Encountered invalid operation %d", code[pos]) + } + + pos += 4 + } + + return code, nil +} + +func solveDay2Part1(inFile string) (int, error) { + raw, err := ioutil.ReadFile(inFile) + if err != nil { + return 0, errors.Wrap(err, "Unable to read input") + } + + code, err := parseDay02Intcode(strings.TrimSpace(string(raw))) + if err != nil { + return 0, errors.Wrap(err, "Unable to parse Intcode") + } + + // Modify data for "1202 program alarm" + code[1] = 12 + code[2] = 2 + + // Execute Intcode + code, err = executeDay02Intcode(code) + if err != nil { + return 0, errors.Wrap(err, "Unable to execute Intcode") + } + + return code[0], nil +} + +func solveDay2Part2(inFile string) (int, error) { + raw, err := ioutil.ReadFile(inFile) + if err != nil { + return 0, errors.Wrap(err, "Unable to read input") + } + + const expectedResult int = 19690720 + + for noun := 0; noun < 100; noun++ { + for verb := 0; verb < 100; verb++ { + + // Re-initialize "memory" + code, err := parseDay02Intcode(strings.TrimSpace(string(raw))) + if err != nil { + return 0, errors.Wrap(err, "Unable to parse Intcode") + } + + // Modify code + code[1] = noun + code[2] = verb + + // Execute Intcode + code, err = executeDay02Intcode(code) + if err != nil { + return 0, errors.Wrap(err, "Unable to execute Intcode") + } + + if code[0] == expectedResult { + return 100*noun + verb, nil + } + + } + } + + return 0, errors.New("No valid result was found") +} diff --git a/day02_input.txt b/day02_input.txt new file mode 100644 index 0000000..e7533e2 --- /dev/null +++ b/day02_input.txt @@ -0,0 +1 @@ +1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,10,19,2,9,19,23,1,9,23,27,2,27,9,31,1,31,5,35,2,35,9,39,1,39,10,43,2,43,13,47,1,47,6,51,2,51,10,55,1,9,55,59,2,6,59,63,1,63,6,67,1,67,10,71,1,71,10,75,2,9,75,79,1,5,79,83,2,9,83,87,1,87,9,91,2,91,13,95,1,95,9,99,1,99,6,103,2,103,6,107,1,107,5,111,1,13,111,115,2,115,6,119,1,119,5,123,1,2,123,127,1,6,127,0,99,2,14,0,0 diff --git a/day02_test.go b/day02_test.go new file mode 100644 index 0000000..3735818 --- /dev/null +++ b/day02_test.go @@ -0,0 +1,47 @@ +package aoc2019 + +import ( + "reflect" + "testing" +) + +func TestExecuteDay02Intcode(t *testing.T) { + for codeStr, expResult := range map[string][]int{ + "1,0,0,0,99": {2, 0, 0, 0, 99}, + "2,3,0,3,99": {2, 3, 0, 6, 99}, + "2,4,4,5,99,0": {2, 4, 4, 5, 99, 9801}, + "1,1,1,4,99,5,6,0,99": {30, 1, 1, 4, 2, 5, 6, 0, 99}, + } { + code, err := parseDay02Intcode(codeStr) + if err != nil { + t.Fatalf("Parsing Intcode failed: %s", err) + } + + res, err := executeDay02Intcode(code) + if err != nil { + t.Fatalf("Intcode execution failed: %s", err) + } + + if !reflect.DeepEqual(res, expResult) { + t.Errorf("Intcode execution yield unexpected result: %+v != %+v", res, expResult) + } + } +} + +func TestCalculateDay2_Part1(t *testing.T) { + codeP0, err := solveDay2Part1("day02_input.txt") + if err != nil { + t.Fatalf("Day 2 solver failed: %s", err) + } + + t.Logf("Solution Day 2 Part 1: %d", codeP0) +} + +func TestCalculateDay2_Part2(t *testing.T) { + result, err := solveDay2Part2("day02_input.txt") + if err != nil { + t.Fatalf("Day 2 solver failed: %s", err) + } + + t.Logf("Solution Day 2 Part 2: %d", result) +}