mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
added day11 solution. added util.RotateGrid
This commit is contained in:
@@ -16,4 +16,4 @@ Day | Name | Type of Algo & Notes
|
||||
8 | Space Image Format | 3D Array manipulation, pretty straight forward
|
||||
9 | Sensor Boost | __MORE INTCODE. YAYY__ 🙃 <br> - A new parameter mode and opcode. <br> - __Really feeling the (tech) debt of some earlier design choices here, went back to refactor day07 before jumping into this one__, then it was a small bit of code for the relative param/opcode & resizing computer memory if necessary
|
||||
10 | Monitoring Station | - This (part2) is my favorite algo... Yes I have a favorite algo <br> Fundamentally it's a geometry problem, angles and trig <br> - Part 1: Calculated via slopes <br> - Part 2: Using Arctangent to find angles an asteroid makes against a vertical line from the home base asteroid. Then those angles can be used to determine if Asteroids are covering each other, AND iterating through all of them can find the next angle Asteroid to vaporize
|
||||
11 | Space Police | - More Intcode stuff... <br>
|
||||
11 | Space Police | - More Intcode stuff... <br> - __2D Array/Slice manipulation__ and a bit of maths/graphing <br> - Implemented a __RotateGrid__ algo
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
IntcodeY struct is defined within this file
|
||||
MakePermutations is in the util package as that will likely be reused
|
||||
*/
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
robotBrain := MakeComputerY(inputNumbers)
|
||||
robotBrain.StepY(0)
|
||||
robotBrain.StepY(0)
|
||||
|
||||
fmt.Println(robotBrain.Outputs)
|
||||
}
|
||||
|
||||
// RobotY struct, x and y are coordinate system based, NOT 2D array 0-indexed
|
||||
type RobotY struct {
|
||||
x int
|
||||
y int
|
||||
Direction string
|
||||
MapCoordsToColor map[string]int
|
||||
}
|
||||
|
||||
// MakeRobotY holds info on the location and direction of the robot only
|
||||
func MakeRobotY(startX, startY int) *RobotY {
|
||||
return &RobotY{
|
||||
startX,
|
||||
startY,
|
||||
"up",
|
||||
make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
// MoveRobotY moves the RobotY
|
||||
func (robot *RobotY) MoveRobotY(direction int) {
|
||||
// direction is the same as the output from the robot brain
|
||||
// i.e. 0 to turn left, 1 to turn right, then step forward 1 space
|
||||
turnLeft := map[string]string{
|
||||
"up": "left",
|
||||
"left": "down",
|
||||
"down": "right",
|
||||
"right": "up",
|
||||
}
|
||||
turnRight := map[string]string{
|
||||
"up": "right",
|
||||
"right": "down",
|
||||
"down": "left",
|
||||
"left": "up",
|
||||
}
|
||||
|
||||
if direction == 0 {
|
||||
robot.Direction = turnLeft[robot.Direction]
|
||||
} else {
|
||||
robot.Direction = turnRight[robot.Direction]
|
||||
}
|
||||
|
||||
switch robot.Direction {
|
||||
case "up":
|
||||
robot.y++
|
||||
case "down":
|
||||
robot.y--
|
||||
case "left":
|
||||
robot.x--
|
||||
case "right":
|
||||
robot.x++
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
IntcodeY is an OOP approach *************************************************
|
||||
MakeComputerY is equivalent to the constructor
|
||||
StepY 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 IntcodeY struct {
|
||||
PuzzleInput []int // file/puzzle input parsed into slice of ints
|
||||
InstructionIndex int // stores the index where the next instruction is
|
||||
Outputs []int // all outputs stored in order
|
||||
IsRunning bool // will be true until a 99 opcode is hit
|
||||
}
|
||||
|
||||
// MakeComputerY initializes a new comp
|
||||
func MakeComputerY(PuzzleInput []int) IntcodeY {
|
||||
puzzleInputCopy := make([]int, len(PuzzleInput))
|
||||
copy(puzzleInputCopy, PuzzleInput)
|
||||
|
||||
comp := IntcodeY{
|
||||
puzzleInputCopy,
|
||||
0,
|
||||
make([]int, 0),
|
||||
true,
|
||||
}
|
||||
|
||||
return comp
|
||||
}
|
||||
|
||||
// StepY will read the next 4 values in the input `sli` and make updates
|
||||
// according to the opcodes
|
||||
func (comp *IntcodeY) StepY(input int) {
|
||||
// read the instruction, opcode and the indexes where the params point to
|
||||
opcode, paramIndexes := comp.GetOpCodeAndParamIndexesY()
|
||||
param1, param2, param3 := paramIndexes[0], paramIndexes[1], paramIndexes[2]
|
||||
|
||||
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
|
||||
comp.StepY(input)
|
||||
case 2: // 2: Multiply next two and store in third
|
||||
comp.PuzzleInput[param3] = comp.PuzzleInput[param1] * comp.PuzzleInput[param2]
|
||||
comp.InstructionIndex += 4
|
||||
comp.StepY(input)
|
||||
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
|
||||
comp.StepY(-1)
|
||||
case 4: // 4: outputs its input value
|
||||
// set LastOutput of the computer & log it
|
||||
comp.Outputs = append(comp.Outputs, comp.PuzzleInput[param1])
|
||||
// fmt.Printf("Opcode 4 output: %v\n", comp.LastOutput)
|
||||
comp.InstructionIndex += 2
|
||||
|
||||
// continue running until terminates or asks for another input
|
||||
comp.StepY(input)
|
||||
// 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
|
||||
}
|
||||
comp.StepY(input)
|
||||
// 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
|
||||
}
|
||||
comp.StepY(input)
|
||||
// 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
|
||||
comp.StepY(input)
|
||||
// 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
|
||||
comp.StepY(input)
|
||||
default:
|
||||
log.Fatalf("Error: unknown opcode %v at index %v", opcode, comp.PuzzleInput[comp.InstructionIndex])
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
GetOpCodeAndParamIndexesY 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 *IntcodeY) GetOpCodeAndParamIndexesY() (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
|
||||
}
|
||||
}
|
||||
|
||||
return opcode, paramIndexes
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
IntcodeX struct is defined within this file
|
||||
MakePermutations is in the util package as that will likely be reused
|
||||
Intcode struct is defined within this file
|
||||
Robot struct contains coordinates and robot's directions
|
||||
- methods can Move the robot based on its brain's (intcode comp.) output
|
||||
Draw function generates a string to display in terminal
|
||||
- helper functions remove some whitespace and rotate the grid/matrix
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -16,6 +19,7 @@ import (
|
||||
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))
|
||||
@@ -23,33 +27,133 @@ func main() {
|
||||
inputNumbers[i], _ = strconv.Atoi(v)
|
||||
}
|
||||
|
||||
// initialize emergency hull painting robot's brain with a 0 for black tile
|
||||
robotBrain := MakeComputerX(inputNumbers)
|
||||
|
||||
// make a robot to find the bounds of movement first
|
||||
// initialize a computer with a senor boost input of `2`
|
||||
robotBrain := MakeComputer(inputNumbers)
|
||||
robot := MakeRobot(0, 0)
|
||||
|
||||
// initialize starting coordinates to a white panel, i.e. 1
|
||||
robot.MapCoordsToColor["0,0"] = 1
|
||||
|
||||
// let robot paint entire map
|
||||
for robotBrain.IsRunning {
|
||||
// a StepX produces two outputs
|
||||
go robotBrain.StepX()
|
||||
coords := fmt.Sprintf("%v,%v", robot.x, robot.y)
|
||||
// get the current color from the robot's map
|
||||
currentCoords := fmt.Sprintf("%v,%v", robot.x, robot.y)
|
||||
currentColor := robot.MapCoordsToColor[currentCoords]
|
||||
robotBrain.Step(currentColor)
|
||||
|
||||
fmt.Println("writing to brain", coords, robot.MapCoordsToColor[coords])
|
||||
robotBrain.InputChannel <- robot.MapCoordsToColor[coords]
|
||||
// get outputs from the robot's brain (Intcode)
|
||||
lenOutputs := len(robotBrain.Outputs)
|
||||
color := robotBrain.Outputs[lenOutputs-2]
|
||||
direction := robotBrain.Outputs[lenOutputs-1]
|
||||
|
||||
color, direction := <-robotBrain.OutputChannel, <-robotBrain.OutputChannel
|
||||
fmt.Printf("color %v, direction %v\n", color, direction)
|
||||
|
||||
// "paint" in the robot map, move the robot
|
||||
robot.MapCoordsToColor[coords] = color
|
||||
// "paint"/update robot's Map and move the robot
|
||||
robot.MapCoordsToColor[currentCoords] = color
|
||||
robot.MoveRobot(direction)
|
||||
fmt.Println(robot)
|
||||
}
|
||||
// then make a 2D grid based on the bounds, then
|
||||
fmt.Printf("Total tiles painted: %v\n", len(robot.MapCoordsToColor))
|
||||
}
|
||||
|
||||
// Robot contains information on the emergency hill painting robot
|
||||
// pass robot.MapCoordsToColor to a "drawing" function
|
||||
output := Draw(robot.MapCoordsToColor)
|
||||
fmt.Println(output)
|
||||
}
|
||||
|
||||
// Draw will return a multiline string using mapCoordsToColor to determine
|
||||
// which cells should be colored white (1) or black/empty (0)
|
||||
func Draw(mapCoordsToColor map[string]int) string {
|
||||
var lowX, highX, lowY, highY int
|
||||
for key := range mapCoordsToColor {
|
||||
coords := strings.Split(key, ",")
|
||||
x, _ := strconv.Atoi(coords[0])
|
||||
y, _ := strconv.Atoi(coords[1])
|
||||
switch {
|
||||
case x < lowX:
|
||||
lowX = x
|
||||
case x > highX:
|
||||
highX = x
|
||||
}
|
||||
switch {
|
||||
case y < lowY:
|
||||
lowY = y
|
||||
case y > highY:
|
||||
highY = y
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the bounds of the grid
|
||||
edgeLength := 2 * util.MaxInts(-lowY, -lowX, highY, highX)
|
||||
|
||||
grid := make([][]string, edgeLength)
|
||||
for i := 0; i < edgeLength; i++ {
|
||||
// each character will initialize as a space character
|
||||
grid[i] = make([]string, edgeLength)
|
||||
for j := range grid[i] {
|
||||
grid[i][j] = " "
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through all coordinates and transcribe x,y onto a 2D grid
|
||||
// where the math is a little different...
|
||||
for key, val := range mapCoordsToColor {
|
||||
// key is string coords
|
||||
coords := strings.Split(key, ",")
|
||||
x, _ := strconv.Atoi(coords[0])
|
||||
y, _ := strconv.Atoi(coords[1])
|
||||
x += edgeLength / 2
|
||||
y += edgeLength / 2
|
||||
// val is color to paint (1 or 0)
|
||||
if val == 1 {
|
||||
grid[x][y] = "#"
|
||||
}
|
||||
}
|
||||
|
||||
// trim off due to making the initial grid too large
|
||||
grid = trim(grid)
|
||||
// rotate it because of how I coded up the robot's coordinates :/
|
||||
grid = util.RotateGrid(grid)
|
||||
// retrim
|
||||
grid = trim(grid)
|
||||
|
||||
// combine each layer into an individual string via join w/ empty string
|
||||
helpMakeFinalString := make([]string, len(grid))
|
||||
for i := range helpMakeFinalString {
|
||||
helpMakeFinalString[i] = strings.Join(grid[i], "")
|
||||
}
|
||||
|
||||
// join all levels together with newlines
|
||||
return strings.Join(helpMakeFinalString, "\n")
|
||||
}
|
||||
|
||||
// helper function for Draw to remove whitespace from overestimating the size
|
||||
// of the drawing space
|
||||
func trim(grid [][]string) [][]string {
|
||||
// remove all empty rows at top and bottom
|
||||
removeRowsTop:
|
||||
for i := 0; i < len(grid); {
|
||||
for j := 0; j < len(grid[i]); j++ {
|
||||
if grid[i][j] != " " {
|
||||
break removeRowsTop
|
||||
}
|
||||
}
|
||||
grid = grid[1:]
|
||||
}
|
||||
|
||||
// remove empty columns on left
|
||||
removeColsLeft:
|
||||
for i := 0; i < len(grid[0]); {
|
||||
for j := 0; j < len(grid); j++ {
|
||||
if grid[j][i] != " " {
|
||||
break removeColsLeft
|
||||
}
|
||||
}
|
||||
// if loop hasn't broken out, iterate over first "column" and slice off "0-index"
|
||||
for j := 0; j < len(grid); j++ {
|
||||
grid[j] = grid[j][1:]
|
||||
}
|
||||
}
|
||||
|
||||
return grid
|
||||
}
|
||||
|
||||
// Robot struct, x and y are coordinate system based, NOT 2D array 0-indexed
|
||||
type Robot struct {
|
||||
x int
|
||||
y int
|
||||
@@ -103,83 +207,86 @@ func (robot *Robot) MoveRobot(direction int) {
|
||||
}
|
||||
|
||||
/*
|
||||
IntcodeX is an OOP approach *************************************************
|
||||
MakeComputerX is equivalent to the constructor
|
||||
StepX takes in an input int and updates properties in the computer:
|
||||
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 IntcodeX struct {
|
||||
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
|
||||
LastOutput int // last output from an opcode 4
|
||||
Outputs []int // stores all outputs
|
||||
IsRunning bool // will be true until a 99 opcode is hit
|
||||
InputChannel chan int // for inputs to computer
|
||||
OutputChannel chan int // for recording all output
|
||||
}
|
||||
|
||||
// MakeComputerX initializes a new comp
|
||||
func MakeComputerX(puzzleInput []int) IntcodeX {
|
||||
puzzleInputCopy := make([]int, len(puzzleInput))
|
||||
copy(puzzleInputCopy, puzzleInput)
|
||||
// MakeComputer initializes a new comp
|
||||
func MakeComputer(PuzzleInput []int) Intcode {
|
||||
puzzleInputCopy := make([]int, len(PuzzleInput))
|
||||
copy(puzzleInputCopy, PuzzleInput)
|
||||
|
||||
comp := IntcodeX{
|
||||
comp := Intcode{
|
||||
puzzleInputCopy,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
make([]int, 0),
|
||||
true,
|
||||
make(chan int),
|
||||
make(chan int),
|
||||
}
|
||||
|
||||
return comp
|
||||
}
|
||||
|
||||
// StepX will read the next 4 values in the input `sli` and make updates
|
||||
// Step will read the next 4 values in the input `sli` and make updates
|
||||
// according to the opcodes
|
||||
func (comp *IntcodeX) StepX() {
|
||||
func (comp *Intcode) Step(input int) {
|
||||
// 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
|
||||
// Note: need to optimize this to not resize if the params are not being used
|
||||
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...")
|
||||
fmt.Println("Terminating...")
|
||||
comp.IsRunning = false
|
||||
// also close output channel
|
||||
close(comp.OutputChannel)
|
||||
case 1: // 1: Add next two paramIndexes, store in third
|
||||
comp.PuzzleInput[param3] = comp.PuzzleInput[param1] + comp.PuzzleInput[param2]
|
||||
comp.InstructionIndex += 4
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
case 2: // 2: Multiply next two and store in third
|
||||
comp.PuzzleInput[param3] = comp.PuzzleInput[param1] * comp.PuzzleInput[param2]
|
||||
comp.InstructionIndex += 4
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
case 3: // 3: Takes one input and saves it to position of one parameter
|
||||
// read an input from input channel
|
||||
input := <-comp.InputChannel
|
||||
// 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
|
||||
go comp.StepX()
|
||||
comp.Step(-1)
|
||||
case 4: // 4: outputs its input value
|
||||
// set LastOutput of the computer & log it
|
||||
comp.LastOutput = comp.PuzzleInput[param1]
|
||||
comp.Outputs = append(comp.Outputs, comp.PuzzleInput[param1])
|
||||
// fmt.Printf("Opcode 4 output: %v\n", comp.LastOutput)
|
||||
comp.InstructionIndex += 2
|
||||
|
||||
// write to output channel
|
||||
comp.OutputChannel <- comp.LastOutput
|
||||
// continue running until terminates or asks for another input
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
// 5: jump-if-true: if first param != 0, move pointer to second param, else nothing
|
||||
case 5:
|
||||
if comp.PuzzleInput[param1] != 0 {
|
||||
@@ -187,7 +294,7 @@ func (comp *IntcodeX) StepX() {
|
||||
} else {
|
||||
comp.InstructionIndex += 3
|
||||
}
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
// 6: jump-if-false, if first param == 0 then set instruction pointer to 2nd param, else nothing
|
||||
case 6:
|
||||
if comp.PuzzleInput[param1] == 0 {
|
||||
@@ -195,7 +302,7 @@ func (comp *IntcodeX) StepX() {
|
||||
} else {
|
||||
comp.InstructionIndex += 3
|
||||
}
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
// 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] {
|
||||
@@ -204,7 +311,7 @@ func (comp *IntcodeX) StepX() {
|
||||
comp.PuzzleInput[param3] = 0
|
||||
}
|
||||
comp.InstructionIndex += 4
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
// 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] {
|
||||
@@ -213,12 +320,12 @@ func (comp *IntcodeX) StepX() {
|
||||
comp.PuzzleInput[param3] = 0
|
||||
}
|
||||
comp.InstructionIndex += 4
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
// 9: adjust relative base
|
||||
case 9:
|
||||
comp.RelativeBase += comp.PuzzleInput[param1]
|
||||
comp.InstructionIndex += 2
|
||||
go comp.StepX()
|
||||
comp.Step(input)
|
||||
default:
|
||||
log.Fatalf("Error: unknown opcode %v at index %v", opcode, comp.PuzzleInput[comp.InstructionIndex])
|
||||
}
|
||||
@@ -230,7 +337,7 @@ GetOpCodeAndParamIndexes will parse the instruction at comp.PuzzleInput[comp.Ins
|
||||
- rest of instructions will be grabbed via mod 10
|
||||
- these also have to be parsed for the
|
||||
*/
|
||||
func (comp *IntcodeX) GetOpCodeAndParamIndexes() (int, [3]int) {
|
||||
func (comp *Intcode) GetOpCodeAndParamIndexes() (int, [3]int) {
|
||||
instruction := comp.PuzzleInput[comp.InstructionIndex]
|
||||
|
||||
// opcode is the lowest two digits, so mod by 100
|
||||
@@ -258,20 +365,19 @@ func (comp *IntcodeX) GetOpCodeAndParamIndexes() (int, [3]int) {
|
||||
}
|
||||
|
||||
// ResizeMemory will take any number of integers and resize the computer's memory appropriately
|
||||
func (comp *IntcodeX) ResizeMemory(sizes ...int) {
|
||||
fmt.Println("resizing", sizes)
|
||||
func (comp *Intcode) ResizeMemory(sizes ...int) {
|
||||
// get largest of input sizes
|
||||
maxArgSize := sizes[0]
|
||||
maxArg := sizes[0]
|
||||
for _, v := range sizes {
|
||||
if v > maxArgSize {
|
||||
maxArgSize = v
|
||||
if v > maxArg {
|
||||
maxArg = v
|
||||
}
|
||||
}
|
||||
|
||||
// resize if PuzzleInput's length is shorter
|
||||
if maxArgSize > len(comp.PuzzleInput) {
|
||||
if maxArg >= len(comp.PuzzleInput) {
|
||||
// make empty slice to copy into, of the new, larger size
|
||||
resizedPuzzleInput := make([]int, maxArgSize)
|
||||
resizedPuzzleInput := make([]int, maxArg+1)
|
||||
// copy old puzzle input values in
|
||||
copy(resizedPuzzleInput, comp.PuzzleInput)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package util
|
||||
|
||||
// MaxInts takes a variable number of integers and returns the largest one
|
||||
func MaxInts(numbers ...int) int {
|
||||
floats := make([]float64, len(numbers))
|
||||
for i, num := range numbers {
|
||||
floats[i] = float64(num)
|
||||
}
|
||||
|
||||
maxNum := floats[0]
|
||||
for i := range floats {
|
||||
if floats[i] > maxNum {
|
||||
maxNum = floats[i]
|
||||
}
|
||||
}
|
||||
|
||||
return int(maxNum)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package util
|
||||
|
||||
// RotateGrid returns the inputted grid, rotated counterclockwise
|
||||
// call it multiple times for 180, & 270 degree rotations
|
||||
// TODO modify this to take in any type (not just strings...)
|
||||
func RotateGrid(grid [][]string) [][]string {
|
||||
rotated := make([][]string, len(grid[0]))
|
||||
for i := range rotated {
|
||||
rotated[i] = make([]string, len(grid))
|
||||
}
|
||||
|
||||
for i := 0; i < len(grid); i++ {
|
||||
for j := 0; j < len(grid[0]); j++ {
|
||||
rotated[len(grid[0])-1-j][i] = grid[i][j]
|
||||
}
|
||||
}
|
||||
return rotated
|
||||
}
|
||||
Reference in New Issue
Block a user