From 0602aad44eb077cee4b7e726cb377c72498344bc Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Thu, 12 Dec 2019 18:16:01 +0100 Subject: [PATCH] Add solution for Day 11 Signed-off-by: Knut Ahlers --- day11.go | 172 ++++++++++++++++++++++++++++++++++++++++++++++++ day11_image.png | Bin 0 -> 206 bytes day11_input.txt | 1 + day11_test.go | 21 ++++++ 4 files changed, 194 insertions(+) create mode 100644 day11.go create mode 100644 day11_image.png create mode 100644 day11_input.txt create mode 100644 day11_test.go diff --git a/day11.go b/day11.go new file mode 100644 index 0000000..088fb1b --- /dev/null +++ b/day11.go @@ -0,0 +1,172 @@ +package aoc2019 + +import ( + "fmt" + "image" + "image/color" + "image/png" + "io/ioutil" + "math" + "os" + "strings" + "sync" + + "github.com/pkg/errors" +) + +type day11PaintDirective struct { + X, Y int + Color int64 +} + +func (d day11PaintDirective) positionKey() string { return fmt.Sprintf("%d:%d", d.X, d.Y) } + +func day11ExecutePaintRobot(inFile string, startPanelColor int64) ([]day11PaintDirective, error) { + var ( + posX, posY int + direction int // Clock-hand direction + directives = map[string]day11PaintDirective{ + "0:0": {X: 0, Y: 0, Color: startPanelColor}, + } + ) + + move := func() { + switch direction { + case 0: + posY -= 1 + case 3: + posX += 1 + case 6: + posY += 1 + case 9: + posX -= 1 + default: + panic(errors.Errorf("Invalid direction: %d", direction)) + } + } + + rotate := func(dir int64) { + var factor int + if dir == 1 { + // turn right + factor = 1 + } else { + // turn left + factor = -1 + } + direction = direction + factor*3 + if direction < 0 { + direction += 12 + } + if direction > 11 { + direction -= 12 + } + } + + // Initialize code + rawCode, err := ioutil.ReadFile(inFile) + if err != nil { + return nil, errors.Wrap(err, "Unable to read intcode") + } + + code, err := parseIntcode(strings.TrimSpace(string(rawCode))) + if err != nil { + return nil, errors.Wrap(err, "Unable to parse intcode") + } + + // Run program in background + var ( + in = make(chan int64, 1) + out = make(chan int64, 2) + outputs []int64 + programExit bool + wg = new(sync.WaitGroup) + ) + + go executeIntcode(code, in, out) + go func() { + for o := range out { + outputs = append(outputs, o) + wg.Done() + } + programExit = true + }() + + // Start feeding scan results + for !programExit { + // Get previous directive for current position + var dir = day11PaintDirective{X: posX, Y: posY} + if d, ok := directives[dir.positionKey()]; ok { + dir = d + } + + // Feed current color and expect two output + wg.Add(2) + in <- dir.Color + wg.Wait() + + // Set current color + dir.Color = outputs[0] + directives[dir.positionKey()] = dir + // Rotate robot + rotate(outputs[1]) + // Move + move() + + // Reset outputs + outputs = nil + } + + var result []day11PaintDirective + for _, v := range directives { + result = append(result, v) + } + + return result, nil +} + +func solveDay11Part1(inFile string) (int, error) { + dirs, err := day11ExecutePaintRobot(inFile, 0) + return len(dirs), errors.Wrap(err, "Unable to execute robot") +} + +func solveDay11Part2(inFile string) error { + dirs, err := day11ExecutePaintRobot(inFile, 1) + if err != nil { + return errors.Wrap(err, "Unable to execute robot") + } + + var minX, minY, maxX, maxY = math.MaxInt64, math.MaxInt64, 0, 0 + for _, dir := range dirs { + if dir.X < minX { + minX = dir.X + } + if dir.X > maxX { + maxX = dir.X + } + if dir.Y < minY { + minY = dir.Y + } + if dir.Y > maxY { + maxY = dir.Y + } + } + + colors := map[int64]color.Color{ + 0: color.RGBA{0x0, 0x0, 0x0, 0xff}, + 1: color.RGBA{0xff, 0xff, 0xff, 0xff}, + } + + img := image.NewRGBA(image.Rect(minX-5, minY-5, maxX+5, maxY+5)) + for _, dir := range dirs { + img.Set(dir.X, dir.Y, colors[dir.Color]) + } + + w, err := os.Create("day11_image.png") + if err != nil { + return errors.Wrap(err, "Unable to open result image file") + } + defer w.Close() + + return errors.Wrap(png.Encode(w, img), "Unable to store image") +} diff --git a/day11_image.png b/day11_image.png new file mode 100644 index 0000000000000000000000000000000000000000..117bcd664191eba15abc65cacb84d59bf3416b2a GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^CP2*3!3HE(AAQpbq^5ehIEGZrc{BAOUz-9?^TYH1 z|E;$MCR`=bhUAcLo?pUXO@ GgeCw?Vo~t` literal 0 HcmV?d00001 diff --git a/day11_input.txt b/day11_input.txt new file mode 100644 index 0000000..a9f3744 --- /dev/null +++ b/day11_input.txt @@ -0,0 +1 @@ +3,8,1005,8,325,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,29,1006,0,41,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,54,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,76,1,9,11,10,2,5,2,10,2,1107,19,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,110,2,1007,10,10,2,1103,13,10,1006,0,34,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,102,1,8,142,1006,0,32,1,101,0,10,2,9,5,10,1006,0,50,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,179,1,1005,11,10,2,1108,11,10,1006,0,10,1,1004,3,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1002,8,1,216,1,1002,12,10,2,1102,3,10,1,1007,4,10,2,101,7,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,102,1,8,253,2,104,3,10,1006,0,70,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,102,1,8,282,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,101,0,8,305,101,1,9,9,1007,9,962,10,1005,10,15,99,109,647,104,0,104,1,21102,838211572492,1,1,21102,342,1,0,1105,1,446,21102,825326674840,1,1,21101,0,353,0,1106,0,446,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29086686211,1,21102,1,400,0,1106,0,446,21102,209420786919,1,1,21101,0,411,0,1105,1,446,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,838337298792,1,21101,434,0,0,1105,1,446,21101,988661154660,0,1,21102,1,445,0,1106,0,446,99,109,2,21201,-1,0,1,21101,40,0,2,21101,0,477,3,21101,0,467,0,1105,1,510,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,472,473,488,4,0,1001,472,1,472,108,4,472,10,1006,10,504,1101,0,0,472,109,-2,2106,0,0,0,109,4,1201,-1,0,509,1207,-3,0,10,1006,10,527,21102,0,1,-3,22102,1,-3,1,22102,1,-2,2,21101,0,1,3,21101,546,0,0,1105,1,551,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,574,2207,-4,-2,10,1006,10,574,21201,-4,0,-4,1105,1,642,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,593,0,1105,1,551,21202,1,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,612,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,634,21202,-1,1,1,21102,1,634,0,105,1,509,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0 diff --git a/day11_test.go b/day11_test.go new file mode 100644 index 0000000..91cba56 --- /dev/null +++ b/day11_test.go @@ -0,0 +1,21 @@ +package aoc2019 + +import "testing" + +func TestCalculateDay11_Part1(t *testing.T) { + count, err := solveDay11Part1("day11_input.txt") + if err != nil { + t.Fatalf("Day 11 solver failed: %s", err) + } + + t.Logf("Solution Day 11 Part 1: %d", count) +} + +func TestCalculateDay11_Part2(t *testing.T) { + err := solveDay11Part2("day11_input.txt") + if err != nil { + t.Fatalf("Day 11 solver failed: %s", err) + } + + t.Log("Solution Day 11 Part 2: See day11_image.png") +}