From 7e23ba3c00a5fa59ca790c344f3452455541897a Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Thu, 6 Aug 2020 23:34:59 -0400 Subject: [PATCH] added day19 solution --- README.md | 1 + day19/input.txt | 1 + day19/part1/main.go | 231 +++++++++++++++++++++++++++++++++++++ day19/part2/main.go | 272 ++++++++++++++++++++++++++++++++++++++++++++ day19/prompt.txt | 78 +++++++++++++ 5 files changed, 583 insertions(+) create mode 100644 day19/input.txt create mode 100644 day19/part1/main.go create mode 100644 day19/part2/main.go create mode 100644 day19/prompt.txt diff --git a/README.md b/README.md index d5921cb..edd2470 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,4 @@ Day | Name | Type of Algo & Notes 16 | Flawed Frequency Transmission | - Some really weird, contrived (as if this whole thing isn't) phase calculator?..
- part2 broke my brain. Optimally calculate subsets by __precalculating running sums__ (linear), then getting subsets by subtracting two of the precalculated running sums. i.e. sub[2:4] = sub[0:4] - sub[0:2]
- And also switching pattern recognition to make calculating a particular output O(nlogn)... 17 | Set and Forget | More Intcode...
Robot walking around a scaffolding... Fairly similar to previous algos, and a 2D grid traversal again
- I feel like I cheated part2 by finding the pattern by eye after printing what the 2D grid looks like. Then it was a matter of giving the intcode computer the corresponding inputs (in a weird format).
- Good example of __iterative approaches being better than recursive approaches__ because the recursive approach in "continuous video mode" causes a stack overflow very quickly 18 | Many-Worlds Interpretation | - Oof, this is the hardest algo so far I think... Combination of __Best Pathfinding Algo__ (going to use a BFS/Dijkstra's) and a weighted __Graph Traversal__ with "locked" edges
- I toyed with the idea of using some kind of bitmap to track keys that were found, but ditched it so I wouldn't have to write my own wrapper around bitwise logic... Time complexity comparisons are roughly similar for comparing two maps as comparing two sets of bits, the space complexity is probably much better for 27-bits (@ and a-z) compared to a hashmap, but OH WELL.
- The graph traversal required memoizing in order to run in any reasonable amount of time.
- My part 2 assumptions would not work for every example which is unfortunate :/ I assumed that within a particular quadrant, if the quadrant does not have the key for a door, just remove the door. +19 | Tractor Beam | - Another Intcode outputting to a 2D grid
- __THERE NEEDS TO BE A CONVENTION FOR X AND Y WHEN WORKING WITH 2D GRIDS__ This is awful, should it be mathematical? Should it represent rows and columns? Who knows?!
\ No newline at end of file diff --git a/day19/input.txt b/day19/input.txt new file mode 100644 index 0000000..2a56b00 --- /dev/null +++ b/day19/input.txt @@ -0,0 +1 @@ +109,424,203,1,21101,11,0,0,1106,0,282,21102,1,18,0,1105,1,259,1202,1,1,221,203,1,21101,0,31,0,1105,1,282,21102,1,38,0,1106,0,259,21001,23,0,2,22102,1,1,3,21102,1,1,1,21102,57,1,0,1106,0,303,2101,0,1,222,21002,221,1,3,21001,221,0,2,21101,0,259,1,21101,80,0,0,1105,1,225,21101,158,0,2,21101,0,91,0,1106,0,303,1201,1,0,223,20102,1,222,4,21101,259,0,3,21101,225,0,2,21102,225,1,1,21101,118,0,0,1106,0,225,20102,1,222,3,21101,0,79,2,21102,1,133,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1105,1,259,2102,1,1,223,21001,221,0,4,20102,1,222,3,21101,16,0,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,0,195,0,106,0,108,20207,1,223,2,20101,0,23,1,21102,-1,1,3,21102,214,1,0,1106,0,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1201,-4,0,249,21202,-3,1,1,21201,-2,0,2,22101,0,-1,3,21101,250,0,0,1106,0,225,21202,1,1,-4,109,-5,2105,1,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2106,0,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22101,0,-2,3,21102,343,1,0,1106,0,303,1106,0,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,22101,0,-4,1,21101,384,0,0,1105,1,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21202,1,1,-4,109,-5,2106,0,0 \ No newline at end of file diff --git a/day19/part1/main.go b/day19/part1/main.go new file mode 100644 index 0000000..252eac8 --- /dev/null +++ b/day19/part1/main.go @@ -0,0 +1,231 @@ +/* +Intcode struct is defined within this file + - Every drone needs its own computer made, I let them get garbage collected as often + as possible, not sure how extendable this is going to be to part 2 +*/ + +package main + +import ( + "adventofcode/util" + "fmt" + "log" + "strconv" + "strings" +) + +func main() { + // read the input file, modify it to a slice of numbers + inputFile := util.ReadFile("../input.txt") + + splitStrings := strings.Split(inputFile, ",") + + inputNumbers := make([]int, len(splitStrings)) + for i, v := range splitStrings { + inputNumbers[i], _ = strconv.Atoi(v) + } + + grid := make([][]string, 50) + var pulledDrones int + for y := 0; y < 50; y++ { + grid[y] = make([]string, 50) + for x := 0; x < 50; x++ { + // NOTE Every drone gets its own computer... + comp := MakeComputer(inputNumbers) + comp.Step(x) + comp.Step(y) + + lastOutput := comp.Outputs[len(comp.Outputs)-1] + if lastOutput == 0 { + grid[y][x] = "." + } else { + grid[y][x] = "#" + pulledDrones++ + } + } + } + + fmt.Println("Total pulled drones", pulledDrones) + + for _, v := range grid { + fmt.Println(v) + } +} + +/* +Intcode is an OOP approach ************************************************* +MakeComputer is equivalent to the constructor +Step takes in an input int and updates properties in the computer: + - InstructionIndex: where to read the next instruction from + - LastOutput, what the last opcode 4 outputted + - PuzzleIndex based if the last instruction modified the puzzle at all +****************************************************************************/ +type Intcode struct { + PuzzleInput []int // file/puzzle input parsed into slice of ints + InstructionIndex int // stores the index where the next instruction is + RelativeBase int // relative base for opcode 9 and param mode 2 + Outputs []int // stores all outputs + IsRunning bool // will be true until a 99 opcode is hit +} + +// MakeComputer initializes a new comp +func MakeComputer(PuzzleInput []int) *Intcode { + puzzleInputCopy := make([]int, len(PuzzleInput)) + copy(puzzleInputCopy, PuzzleInput) + + comp := Intcode{ + puzzleInputCopy, + 0, + 0, + make([]int, 0), + true, + } + return &comp +} + +// Step will read the next 4 values in the input `sli` and make updates +// according to the opcodes +// Update to run iteratively (while the computer is running) +// it will also return out if a -1 input is asked for +// then call Step again to provide the next input, or run with -1 from the start +// to run the computer until it asks for an input OR terminates +func (comp *Intcode) Step(input int) { + for comp.IsRunning { + // read the instruction, opcode and the indexes where the params point to + opcode, paramIndexes := comp.GetOpCodeAndParamIndexes() + param1, param2, param3 := paramIndexes[0], paramIndexes[1], paramIndexes[2] + + // ensure params are within the bounds of PuzzleInput, resize if necessary + switch opcode { + case 1, 2, 7, 8: + comp.ResizeMemory(param1, param2, param3) + case 5, 6: + comp.ResizeMemory(param1, param2) + case 3, 4, 9: + comp.ResizeMemory(param1) + } + + switch opcode { + case 99: // 99: Terminates program + // fmt.Println("Terminating...") + comp.IsRunning = false + case 1: // 1: Add next two paramIndexes, store in third + comp.PuzzleInput[param3] = comp.PuzzleInput[param1] + comp.PuzzleInput[param2] + comp.InstructionIndex += 4 + case 2: // 2: Multiply next two and store in third + comp.PuzzleInput[param3] = comp.PuzzleInput[param1] * comp.PuzzleInput[param2] + comp.InstructionIndex += 4 + case 3: // 3: Takes one input and saves it to position of one parameter + // check if input has already been used (i.e. input == -1) + // if it's been used, return out to prevent further Steps + // NOTE: making a big assumption that -1 will never be an input... + if input == -1 { + return + } + + // else recurse with a -1 to signal the initial input has been processed + comp.PuzzleInput[param1] = input + comp.InstructionIndex += 2 + + // change the input value so the next time a 3 opcode is hit, will return out + input = -1 + case 4: // 4: outputs its input value + output := comp.PuzzleInput[param1] + // set LastOutput of the computer & log it + comp.Outputs = append(comp.Outputs, output) + + comp.InstructionIndex += 2 + // 5: jump-if-true: if first param != 0, move pointer to second param, else nothing + case 5: + if comp.PuzzleInput[param1] != 0 { + comp.InstructionIndex = comp.PuzzleInput[param2] + } else { + comp.InstructionIndex += 3 + } + // 6: jump-if-false, if first param == 0 then set instruction pointer to 2nd param, else nothing + case 6: + if comp.PuzzleInput[param1] == 0 { + comp.InstructionIndex = comp.PuzzleInput[param2] + } else { + comp.InstructionIndex += 3 + } + // 7: less-than, if param1 < param2 then store 1 in postion of 3rd param, else store 0 + case 7: + if comp.PuzzleInput[param1] < comp.PuzzleInput[param2] { + comp.PuzzleInput[param3] = 1 + } else { + comp.PuzzleInput[param3] = 0 + } + comp.InstructionIndex += 4 + // 8: equals, if param1 == param2 then set position of 3rd param to 1, else store 0 + case 8: + if comp.PuzzleInput[param1] == comp.PuzzleInput[param2] { + comp.PuzzleInput[param3] = 1 + } else { + comp.PuzzleInput[param3] = 0 + } + comp.InstructionIndex += 4 + // 9: adjust relative base + case 9: + comp.RelativeBase += comp.PuzzleInput[param1] + comp.InstructionIndex += 2 + default: + log.Fatalf("Error: unknown opcode %v at index %v", opcode, comp.PuzzleInput[comp.InstructionIndex]) + } + } +} + +/* +GetOpCodeAndParamIndexes will parse the instruction at comp.PuzzleInput[comp.InstructionIndex] +- opcode will be the left two digits, mod by 100 will get that +- rest of instructions will be grabbed via mod 10 + - these also have to be parsed for the +*/ +func (comp *Intcode) GetOpCodeAndParamIndexes() (int, [3]int) { + instruction := comp.PuzzleInput[comp.InstructionIndex] + + // opcode is the lowest two digits, so mod by 100 + opcode := instruction % 100 + instruction /= 100 + + // assign the indexes that need to be read by reading the parameter modes + var paramIndexes [3]int + for i := 1; i <= 3 && comp.InstructionIndex+i < len(comp.PuzzleInput); i++ { + // grab the mode with a mod, last digit + mode := instruction % 10 + instruction /= 10 + + switch mode { + case 0: // position mode, index will be the value at the index + paramIndexes[i-1] = comp.PuzzleInput[comp.InstructionIndex+i] + case 1: // immediate mode, the index itself + paramIndexes[i-1] = comp.InstructionIndex + i + case 2: // relative mode, like position mode but index is added to relative base + paramIndexes[i-1] = comp.PuzzleInput[comp.InstructionIndex+i] + comp.RelativeBase + } + } + + return opcode, paramIndexes +} + +// ResizeMemory will take any number of integers and resize the computer's memory appropriately +func (comp *Intcode) ResizeMemory(sizes ...int) { + // get largest of input sizes + maxArg := sizes[0] + for _, v := range sizes { + if v > maxArg { + maxArg = v + } + } + + // resize if PuzzleInput's length is shorter + if maxArg >= len(comp.PuzzleInput) { + // make empty slice to copy into, of the new, larger size + resizedPuzzleInput := make([]int, maxArg+1) + // copy old puzzle input values in + copy(resizedPuzzleInput, comp.PuzzleInput) + + // overwrite puzzle input + comp.PuzzleInput = resizedPuzzleInput + } +} diff --git a/day19/part2/main.go b/day19/part2/main.go new file mode 100644 index 0000000..2b8f380 --- /dev/null +++ b/day19/part2/main.go @@ -0,0 +1,272 @@ +/* +Intcode struct is defined within this file + - Every drone needs its own computer made, I let them get garbage collected as often + as possible, not sure how extendable this is going to be to part 2 +*/ + +package main + +import ( + "adventofcode/util" + "fmt" + "log" + "strconv" + "strings" +) + +func main() { + // read the input file, modify it to a slice of numbers + inputFile := util.ReadFile("../input.txt") + + splitStrings := strings.Split(inputFile, ",") + + inputNumbers := make([]int, len(splitStrings)) + for i, v := range splitStrings { + inputNumbers[i], _ = strconv.Atoi(v) + } + + // x, y := 1135, 1625 + + allHorizontalRanges := [][2]int{ + [2]int{0, 1}, + } + + for len(allHorizontalRanges) < 5000 { + startOfLastRange := allHorizontalRanges[len(allHorizontalRanges)-1][0] + horizontalRange := getHorizontalRange(inputNumbers, startOfLastRange, len(allHorizontalRanges)) + allHorizontalRanges = append(allHorizontalRanges, horizontalRange) + + if len(allHorizontalRanges) > 100 { + // indexes of the current line and 100 rows up + currentIndex := len(allHorizontalRanges) - 1 + index100RowsUp := len(allHorizontalRanges) - 100 + + // check if a square can fit from the start of the current range to the end of the range 100 rows up + if allHorizontalRanges[index100RowsUp][1]-allHorizontalRanges[currentIndex][0] >= 99 { + // Print the AoC format + fmt.Println("AoC answer:", allHorizontalRanges[currentIndex][0]*10000+index100RowsUp) + + break + } + } + } +} + +func getHorizontalRange(inputNumbers []int, startX, y int) [2]int { + horizontalRange := [2]int{} + + var lastOutput int + + // step until the output is a one + // OR exit condition of 10 cells have all returned zeroes (this will apply for some of the first levels) + for x := startX; lastOutput == 0; x++ { + lastOutput = makeDroneAndTest(inputNumbers, x, y) + // when the first element is found that is "pulled", set the start of the range + if lastOutput == 1 { + horizontalRange[0] = x + } + + // NOTE edge case for the first few rows if none of the drones are pulled + if x > startX+20 { + return [2]int{0, 0} + } + + } + + for x := horizontalRange[0] + 1; lastOutput != 0; x++ { + lastOutput = makeDroneAndTest(inputNumbers, x, y) + + if lastOutput == 0 { + horizontalRange[1] = x - 1 + } + } + + return horizontalRange +} + +func makeDroneAndTest(inputNumbers []int, x, y int) int { + drone := MakeComputer(inputNumbers) + drone.Step(x) + drone.Step(y) + lastOutput := drone.Outputs[len(drone.Outputs)-1] + + return lastOutput +} + +/* +Intcode is an OOP approach ************************************************* +MakeComputer is equivalent to the constructor +Step takes in an input int and updates properties in the computer: + - InstructionIndex: where to read the next instruction from + - LastOutput, what the last opcode 4 outputted + - PuzzleIndex based if the last instruction modified the puzzle at all +****************************************************************************/ +type Intcode struct { + PuzzleInput []int // file/puzzle input parsed into slice of ints + InstructionIndex int // stores the index where the next instruction is + RelativeBase int // relative base for opcode 9 and param mode 2 + Outputs []int // stores all outputs + IsRunning bool // will be true until a 99 opcode is hit +} + +// MakeComputer initializes a new comp +func MakeComputer(PuzzleInput []int) *Intcode { + puzzleInputCopy := make([]int, len(PuzzleInput)) + copy(puzzleInputCopy, PuzzleInput) + + comp := Intcode{ + puzzleInputCopy, + 0, + 0, + make([]int, 0), + true, + } + return &comp +} + +// Step will read the next 4 values in the input `sli` and make updates +// according to the opcodes +// Update to run iteratively (while the computer is running) +// it will also return out if a -1 input is asked for +// then call Step again to provide the next input, or run with -1 from the start +// to run the computer until it asks for an input OR terminates +func (comp *Intcode) Step(input int) { + for comp.IsRunning { + // read the instruction, opcode and the indexes where the params point to + opcode, paramIndexes := comp.GetOpCodeAndParamIndexes() + param1, param2, param3 := paramIndexes[0], paramIndexes[1], paramIndexes[2] + + // ensure params are within the bounds of PuzzleInput, resize if necessary + switch opcode { + case 1, 2, 7, 8: + comp.ResizeMemory(param1, param2, param3) + case 5, 6: + comp.ResizeMemory(param1, param2) + case 3, 4, 9: + comp.ResizeMemory(param1) + } + + switch opcode { + case 99: // 99: Terminates program + // fmt.Println("Terminating...") + comp.IsRunning = false + case 1: // 1: Add next two paramIndexes, store in third + comp.PuzzleInput[param3] = comp.PuzzleInput[param1] + comp.PuzzleInput[param2] + comp.InstructionIndex += 4 + case 2: // 2: Multiply next two and store in third + comp.PuzzleInput[param3] = comp.PuzzleInput[param1] * comp.PuzzleInput[param2] + comp.InstructionIndex += 4 + case 3: // 3: Takes one input and saves it to position of one parameter + // check if input has already been used (i.e. input == -1) + // if it's been used, return out to prevent further Steps + // NOTE: making a big assumption that -1 will never be an input... + if input == -1 { + return + } + + // else recurse with a -1 to signal the initial input has been processed + comp.PuzzleInput[param1] = input + comp.InstructionIndex += 2 + + // change the input value so the next time a 3 opcode is hit, will return out + input = -1 + case 4: // 4: outputs its input value + output := comp.PuzzleInput[param1] + // set LastOutput of the computer & log it + comp.Outputs = append(comp.Outputs, output) + + comp.InstructionIndex += 2 + // 5: jump-if-true: if first param != 0, move pointer to second param, else nothing + case 5: + if comp.PuzzleInput[param1] != 0 { + comp.InstructionIndex = comp.PuzzleInput[param2] + } else { + comp.InstructionIndex += 3 + } + // 6: jump-if-false, if first param == 0 then set instruction pointer to 2nd param, else nothing + case 6: + if comp.PuzzleInput[param1] == 0 { + comp.InstructionIndex = comp.PuzzleInput[param2] + } else { + comp.InstructionIndex += 3 + } + // 7: less-than, if param1 < param2 then store 1 in postion of 3rd param, else store 0 + case 7: + if comp.PuzzleInput[param1] < comp.PuzzleInput[param2] { + comp.PuzzleInput[param3] = 1 + } else { + comp.PuzzleInput[param3] = 0 + } + comp.InstructionIndex += 4 + // 8: equals, if param1 == param2 then set position of 3rd param to 1, else store 0 + case 8: + if comp.PuzzleInput[param1] == comp.PuzzleInput[param2] { + comp.PuzzleInput[param3] = 1 + } else { + comp.PuzzleInput[param3] = 0 + } + comp.InstructionIndex += 4 + // 9: adjust relative base + case 9: + comp.RelativeBase += comp.PuzzleInput[param1] + comp.InstructionIndex += 2 + default: + log.Fatalf("Error: unknown opcode %v at index %v", opcode, comp.PuzzleInput[comp.InstructionIndex]) + } + } +} + +/* +GetOpCodeAndParamIndexes will parse the instruction at comp.PuzzleInput[comp.InstructionIndex] +- opcode will be the left two digits, mod by 100 will get that +- rest of instructions will be grabbed via mod 10 + - these also have to be parsed for the +*/ +func (comp *Intcode) GetOpCodeAndParamIndexes() (int, [3]int) { + instruction := comp.PuzzleInput[comp.InstructionIndex] + + // opcode is the lowest two digits, so mod by 100 + opcode := instruction % 100 + instruction /= 100 + + // assign the indexes that need to be read by reading the parameter modes + var paramIndexes [3]int + for i := 1; i <= 3 && comp.InstructionIndex+i < len(comp.PuzzleInput); i++ { + // grab the mode with a mod, last digit + mode := instruction % 10 + instruction /= 10 + + switch mode { + case 0: // position mode, index will be the value at the index + paramIndexes[i-1] = comp.PuzzleInput[comp.InstructionIndex+i] + case 1: // immediate mode, the index itself + paramIndexes[i-1] = comp.InstructionIndex + i + case 2: // relative mode, like position mode but index is added to relative base + paramIndexes[i-1] = comp.PuzzleInput[comp.InstructionIndex+i] + comp.RelativeBase + } + } + + return opcode, paramIndexes +} + +// ResizeMemory will take any number of integers and resize the computer's memory appropriately +func (comp *Intcode) ResizeMemory(sizes ...int) { + // get largest of input sizes + maxArg := sizes[0] + for _, v := range sizes { + if v > maxArg { + maxArg = v + } + } + + // resize if PuzzleInput's length is shorter + if maxArg >= len(comp.PuzzleInput) { + // make empty slice to copy into, of the new, larger size + resizedPuzzleInput := make([]int, maxArg+1) + // copy old puzzle input values in + copy(resizedPuzzleInput, comp.PuzzleInput) + + // overwrite puzzle input + comp.PuzzleInput = resizedPuzzleInput + } +} diff --git a/day19/prompt.txt b/day19/prompt.txt new file mode 100644 index 0000000..0c8f632 --- /dev/null +++ b/day19/prompt.txt @@ -0,0 +1,78 @@ +--- Day 19: Tractor Beam --- +Unsure of the state of Santa's ship, you borrowed the tractor beam technology from Triton. Time to test it out. + +When you're safely away from anything else, you activate the tractor beam, but nothing happens. It's hard to tell whether it's working if there's nothing to use it on. Fortunately, your ship's drone system can be configured to deploy a drone to specific coordinates and then check whether it's being pulled. There's even an Intcode program (your puzzle input) that gives you access to the drone system. + +The program uses two input instructions to request the X and Y position to which the drone should be deployed. Negative numbers are invalid and will confuse the drone; all numbers should be zero or positive. + +Then, the program will output whether the drone is stationary (0) or being pulled by something (1). For example, the coordinate X=0, Y=0 is directly in front of the tractor beam emitter, so the drone control program will always report 1 at that location. + +To better understand the tractor beam, it is important to get a good picture of the beam itself. For example, suppose you scan the 10x10 grid of points closest to the emitter: + + X + 0-> 9 + 0#......... + |.#........ + v..##...... + ...###.... + ....###... +Y .....####. + ......#### + ......#### + .......### + 9........## +In this example, the number of points affected by the tractor beam in the 10x10 area closest to the emitter is 27. + +However, you'll need to scan a larger area to understand the shape of the beam. How many points are affected by the tractor beam in the 50x50 area closest to the emitter? (For each of X and Y, this will be 0 through 49.) + +Your puzzle answer was 126. + +--- Part Two --- +You aren't sure how large Santa's ship is. You aren't even sure if you'll need to use this thing on Santa's ship, but it doesn't hurt to be prepared. You figure Santa's ship might fit in a 100x100 square. + +The beam gets wider as it travels away from the emitter; you'll need to be a minimum distance away to fit a square of that size into the beam fully. (Don't rotate the square; it should be aligned to the same axes as the drone grid.) + +For example, suppose you have the following tractor beam readings: + +#....................................... +.#...................................... +..##.................................... +...###.................................. +....###................................. +.....####............................... +......#####............................. +......######............................ +.......#######.......................... +........########........................ +.........#########...................... +..........#########..................... +...........##########................... +...........############................. +............############................ +.............#############.............. +..............##############............ +...............###############.......... +................###############......... +................#################....... +.................########OOOOOOOOOO..... +..................#######OOOOOOOOOO#.... +...................######OOOOOOOOOO###.. +....................#####OOOOOOOOOO##### +.....................####OOOOOOOOOO##### +.....................####OOOOOOOOOO##### +......................###OOOOOOOOOO##### +.......................##OOOOOOOOOO##### +........................#OOOOOOOOOO##### +.........................OOOOOOOOOO##### +..........................############## +..........................############## +...........................############# +............................############ +.............................########### +In this example, the 10x10 square closest to the emitter that fits entirely within the tractor beam has been marked O. Within it, the point closest to the emitter (the only highlighted O) is at X=25, Y=20. + +Find the 100x100 square closest to the emitter that fits entirely within the tractor beam; within that square, find the point closest to the emitter. What value do you get if you take that point's X coordinate, multiply it by 10000, then add the point's Y coordinate? (In the example above, this would be 250020.) + +Your puzzle answer was 11351625. + +Both parts of this puzzle are complete! They provide two gold stars: **