mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-06-07 12:45:10 +02:00
refactor of day07 solution
This commit is contained in:
@@ -12,4 +12,4 @@ Day | Name | Type of Algo & Notes
|
||||
4 | Secure Container | - May appear math-y, but it's really a string manipulation problem
|
||||
5 | Sunny with a Chance of Asteroids | - Yay more Intcode!........ <br> - This gave me fits... <br> - Good application for recursion (in my opinion)
|
||||
6 | Universal Orbit Map | - __Tree traversal__ and depth calculations. It's not quite a Graph, but it has a __directed graph__ algo feel too
|
||||
7 | Amplification Circuit | - More Intcode... Piping together multiple Intcode computers 😳😳😳
|
||||
7 | Amplification Circuit | - More Intcode... Piping together multiple Intcode computers 😳😳😳 <br> - Refactored Intcode computer to an OOP approach so a single computer maintains its data <br> - Also requires making __permutations generator__ <br> - Some gymnastics to make this circular, but its easier with this OOP approach and the "objects"/instances of a struct maintaining their own data
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
package intcode
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Intcode runs the intcode computer on an inputted slice
|
||||
// func Intcode(puzzleInput []int) {
|
||||
// // default input slice, index 1 and 2 will be replaced
|
||||
// // puzzleInput := []int{3, 225, 1, 225, 6, 6, 1100, 1, 238, 225, 104, 0, 1, 192, 154, 224, 101, -161, 224, 224, 4, 224, 102, 8, 223, 223, 101, 5, 224, 224, 1, 223, 224, 223, 1001, 157, 48, 224, 1001, 224, -61, 224, 4, 224, 102, 8, 223, 223, 101, 2, 224, 224, 1, 223, 224, 223, 1102, 15, 28, 225, 1002, 162, 75, 224, 1001, 224, -600, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 1, 224, 1, 224, 223, 223, 102, 32, 57, 224, 1001, 224, -480, 224, 4, 224, 102, 8, 223, 223, 101, 1, 224, 224, 1, 224, 223, 223, 1101, 6, 23, 225, 1102, 15, 70, 224, 1001, 224, -1050, 224, 4, 224, 1002, 223, 8, 223, 101, 5, 224, 224, 1, 224, 223, 223, 101, 53, 196, 224, 1001, 224, -63, 224, 4, 224, 102, 8, 223, 223, 1001, 224, 3, 224, 1, 224, 223, 223, 1101, 64, 94, 225, 1102, 13, 23, 225, 1101, 41, 8, 225, 2, 105, 187, 224, 1001, 224, -60, 224, 4, 224, 1002, 223, 8, 223, 101, 6, 224, 224, 1, 224, 223, 223, 1101, 10, 23, 225, 1101, 16, 67, 225, 1101, 58, 10, 225, 1101, 25, 34, 224, 1001, 224, -59, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 3, 224, 1, 223, 224, 223, 4, 223, 99, 0, 0, 0, 677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1105, 0, 99999, 1105, 227, 247, 1105, 1, 99999, 1005, 227, 99999, 1005, 0, 256, 1105, 1, 99999, 1106, 227, 99999, 1106, 0, 265, 1105, 1, 99999, 1006, 0, 99999, 1006, 227, 274, 1105, 1, 99999, 1105, 1, 280, 1105, 1, 99999, 1, 225, 225, 225, 1101, 294, 0, 0, 105, 1, 0, 1105, 1, 99999, 1106, 0, 300, 1105, 1, 99999, 1, 225, 225, 225, 1101, 314, 0, 0, 106, 0, 0, 1105, 1, 99999, 1108, 226, 226, 224, 102, 2, 223, 223, 1005, 224, 329, 101, 1, 223, 223, 107, 226, 226, 224, 1002, 223, 2, 223, 1005, 224, 344, 1001, 223, 1, 223, 107, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 359, 101, 1, 223, 223, 7, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 374, 101, 1, 223, 223, 108, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 389, 101, 1, 223, 223, 1007, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 404, 101, 1, 223, 223, 7, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 419, 101, 1, 223, 223, 1107, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 434, 1001, 223, 1, 223, 1108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 449, 101, 1, 223, 223, 108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 464, 1001, 223, 1, 223, 8, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 479, 1001, 223, 1, 223, 1007, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 494, 101, 1, 223, 223, 1008, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 509, 101, 1, 223, 223, 1107, 677, 226, 224, 1002, 223, 2, 223, 1006, 224, 524, 1001, 223, 1, 223, 108, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 539, 1001, 223, 1, 223, 1107, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 554, 1001, 223, 1, 223, 7, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 569, 1001, 223, 1, 223, 8, 677, 226, 224, 102, 2, 223, 223, 1006, 224, 584, 101, 1, 223, 223, 1008, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 599, 101, 1, 223, 223, 1007, 226, 677, 224, 1002, 223, 2, 223, 1006, 224, 614, 1001, 223, 1, 223, 8, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 629, 101, 1, 223, 223, 107, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 644, 101, 1, 223, 223, 1108, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 659, 101, 1, 223, 223, 1008, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 674, 1001, 223, 1, 223, 4, 223, 99, 226}
|
||||
|
||||
// // Part 1: ID of System is 1 (use as the input)
|
||||
// // runDiagnostics(puzzleInput, 1)
|
||||
|
||||
// // Part 2: ID of System is 5 (use as the input)
|
||||
// RunDiagnostics(puzzleInput, 0)
|
||||
// }
|
||||
|
||||
// RunDiagnostics runs the entire computer on a puzzleInput and an inputValue
|
||||
func RunDiagnostics(puzzleInput []int, inputValue int, secondInputValue int) int {
|
||||
// store the lastOutputValue to be returned upon a 99
|
||||
var lastOutputValue int
|
||||
|
||||
for i := 0; i < len(puzzleInput); {
|
||||
// find op code (last 2 digits of number), a 1, 2, 3, 4, or 99
|
||||
// find param1 and param2 which are the 100's and 1000's digit in the i-th element
|
||||
opCode, param1, param2, _ := returnCodes(puzzleInput[i])
|
||||
var firstVal, secondVal, thirdVal int
|
||||
|
||||
// set value variables based on what the opCodes are (some of them will throw errors if I attempt to set them...)
|
||||
if opCode == 1 || opCode == 2 || opCode == 7 || opCode == 8 {
|
||||
firstVal, secondVal = getValue(puzzleInput, param1, puzzleInput[i+1]), getValue(puzzleInput, param2, puzzleInput[i+2])
|
||||
thirdVal = puzzleInput[i+3]
|
||||
} else if opCode == 3 || opCode == 4 {
|
||||
firstVal = puzzleInput[i+1]
|
||||
} else if opCode == 5 || opCode == 6 {
|
||||
firstVal, secondVal = getValue(puzzleInput, param1, puzzleInput[i+1]), getValue(puzzleInput, param2, puzzleInput[i+2])
|
||||
}
|
||||
|
||||
// switch statement to handle the opcode value
|
||||
switch opCode {
|
||||
case 99:
|
||||
fmt.Println("99 halts IntCode instance")
|
||||
return lastOutputValue
|
||||
case 1:
|
||||
// add and place (by position)
|
||||
// firstToAdd, secondToAdd := getValue(puzzleInput, param1, puzzleInput[i+1]), getValue(puzzleInput, param2, puzzleInput[i+2])
|
||||
puzzleInput[thirdVal] = firstVal + secondVal
|
||||
i += 4
|
||||
case 2:
|
||||
// multiply and place (by position)
|
||||
puzzleInput[thirdVal] = firstVal * secondVal
|
||||
i += 4
|
||||
case 3:
|
||||
fmt.Println("--INPUT OPCODE 3")
|
||||
// write inputValue to puzzle input by position
|
||||
puzzleInput[firstVal] = inputValue
|
||||
|
||||
// adding functionality for a second input value (to get the above lines to use it, overwrite the inputValue variable with the next argument that was passed in)
|
||||
inputValue = secondInputValue
|
||||
i += 2
|
||||
case 4:
|
||||
// output the value to the console, always by position
|
||||
fmt.Println("output: ", puzzleInput[firstVal])
|
||||
lastOutputValue = puzzleInput[firstVal]
|
||||
i += 2
|
||||
case 5:
|
||||
// jump-if-true
|
||||
// if first param is != 0 set instruction pointer to value from second parameter
|
||||
if firstVal != 0 {
|
||||
// fmt.Println("5 moves i to", secondVal)
|
||||
i = secondVal
|
||||
} else {
|
||||
// otherwise do nothing except increment i
|
||||
// increment by 3 (like opCode 6)
|
||||
i += 3
|
||||
}
|
||||
case 6:
|
||||
// jump-if-false
|
||||
// if first param is != 0 set instruction pointer to value from second parameter
|
||||
if firstVal == 0 {
|
||||
i = secondVal
|
||||
} else {
|
||||
// otherwise increment i to the next instruction
|
||||
// this instruction has 3 values, so i increments by 3
|
||||
i += 3
|
||||
}
|
||||
case 7:
|
||||
// less than - if firstVal < secondVal, store a 1 @ position of thirdVal, otherwise store a 0
|
||||
if firstVal < secondVal {
|
||||
puzzleInput[thirdVal] = 1
|
||||
} else {
|
||||
puzzleInput[thirdVal] = 0
|
||||
}
|
||||
i += 4
|
||||
case 8:
|
||||
// equals, same as opCode 7 but conditional is firstVal is equal to secondVal
|
||||
if firstVal == secondVal {
|
||||
puzzleInput[thirdVal] = 1
|
||||
} else {
|
||||
puzzleInput[thirdVal] = 0
|
||||
}
|
||||
i += 4
|
||||
default:
|
||||
fmt.Println("bad opCode!!! returning -999")
|
||||
return -999
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("shouldn't have reached end of function, returning -1000")
|
||||
return -1000
|
||||
}
|
||||
|
||||
func returnCodes(number int) (int, int, int, int) {
|
||||
return number % 100, (number % 1000) / 100, (number % 10000) / 1000, (number % 100000) / 10000
|
||||
}
|
||||
|
||||
func getValue(puzzleInput []int, positionOrImmediateCode int, nextOrTwoPastValue int) int {
|
||||
// read if the param is for position or immediate mode and return the value (to be added or multiplied)
|
||||
if positionOrImmediateCode == 0 {
|
||||
// 0 is position mode
|
||||
return puzzleInput[nextOrTwoPastValue]
|
||||
}
|
||||
// otherwise it's immediate mode (no-else-return)
|
||||
return nextOrTwoPastValue
|
||||
}
|
||||
|
||||
// note: a solution to part 1 that I looked up to get some insight into golang
|
||||
// package main
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "math"
|
||||
// "os"
|
||||
// )
|
||||
|
||||
// func main() {
|
||||
|
||||
// // var instructionStrings []string
|
||||
// var results []int
|
||||
// // input := 1
|
||||
|
||||
// // file, err := os.Open("./input.txt")
|
||||
// // if err != nil {
|
||||
// // log.Fatal(err)
|
||||
// // }
|
||||
// // defer file.Close()
|
||||
|
||||
// // scanner := bufio.NewScanner(file)
|
||||
// // for scanner.Scan() {
|
||||
// // line := scanner.Text()
|
||||
// // instructionStrings = strings.Split(line, ",")
|
||||
// // }
|
||||
|
||||
// // instructions := make([]int, len(instructionStrings))
|
||||
|
||||
// // for i, v := range instructionStrings {
|
||||
// // instructions[i], _ = strconv.Atoi(v)
|
||||
// // }
|
||||
|
||||
// // note pasted in instructions slice
|
||||
// instructions := []int{3, 225, 1, 225, 6, 6, 1100, 1, 238, 225, 104, 0, 1, 192, 154, 224, 101, -161, 224, 224, 4, 224, 102, 8, 223, 223, 101, 5, 224, 224, 1, 223, 224, 223, 1001, 157, 48, 224, 1001, 224, -61, 224, 4, 224, 102, 8, 223, 223, 101, 2, 224, 224, 1, 223, 224, 223, 1102, 15, 28, 225, 1002, 162, 75, 224, 1001, 224, -600, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 1, 224, 1, 224, 223, 223, 102, 32, 57, 224, 1001, 224, -480, 224, 4, 224, 102, 8, 223, 223, 101, 1, 224, 224, 1, 224, 223, 223, 1101, 6, 23, 225, 1102, 15, 70, 224, 1001, 224, -1050, 224, 4, 224, 1002, 223, 8, 223, 101, 5, 224, 224, 1, 224, 223, 223, 101, 53, 196, 224, 1001, 224, -63, 224, 4, 224, 102, 8, 223, 223, 1001, 224, 3, 224, 1, 224, 223, 223, 1101, 64, 94, 225, 1102, 13, 23, 225, 1101, 41, 8, 225, 2, 105, 187, 224, 1001, 224, -60, 224, 4, 224, 1002, 223, 8, 223, 101, 6, 224, 224, 1, 224, 223, 223, 1101, 10, 23, 225, 1101, 16, 67, 225, 1101, 58, 10, 225, 1101, 25, 34, 224, 1001, 224, -59, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 3, 224, 1, 223, 224, 223, 4, 223, 99, 0, 0, 0, 677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1105, 0, 99999, 1105, 227, 247, 1105, 1, 99999, 1005, 227, 99999, 1005, 0, 256, 1105, 1, 99999, 1106, 227, 99999, 1106, 0, 265, 1105, 1, 99999, 1006, 0, 99999, 1006, 227, 274, 1105, 1, 99999, 1105, 1, 280, 1105, 1, 99999, 1, 225, 225, 225, 1101, 294, 0, 0, 105, 1, 0, 1105, 1, 99999, 1106, 0, 300, 1105, 1, 99999, 1, 225, 225, 225, 1101, 314, 0, 0, 106, 0, 0, 1105, 1, 99999, 1108, 226, 226, 224, 102, 2, 223, 223, 1005, 224, 329, 101, 1, 223, 223, 107, 226, 226, 224, 1002, 223, 2, 223, 1005, 224, 344, 1001, 223, 1, 223, 107, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 359, 101, 1, 223, 223, 7, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 374, 101, 1, 223, 223, 108, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 389, 101, 1, 223, 223, 1007, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 404, 101, 1, 223, 223, 7, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 419, 101, 1, 223, 223, 1107, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 434, 1001, 223, 1, 223, 1108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 449, 101, 1, 223, 223, 108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 464, 1001, 223, 1, 223, 8, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 479, 1001, 223, 1, 223, 1007, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 494, 101, 1, 223, 223, 1008, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 509, 101, 1, 223, 223, 1107, 677, 226, 224, 1002, 223, 2, 223, 1006, 224, 524, 1001, 223, 1, 223, 108, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 539, 1001, 223, 1, 223, 1107, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 554, 1001, 223, 1, 223, 7, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 569, 1001, 223, 1, 223, 8, 677, 226, 224, 102, 2, 223, 223, 1006, 224, 584, 101, 1, 223, 223, 1008, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 599, 101, 1, 223, 223, 1007, 226, 677, 224, 1002, 223, 2, 223, 1006, 224, 614, 1001, 223, 1, 223, 8, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 629, 101, 1, 223, 223, 107, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 644, 101, 1, 223, 223, 1108, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 659, 101, 1, 223, 223, 1008, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 674, 1001, 223, 1, 223, 4, 223, 99, 226}
|
||||
// input := 1
|
||||
|
||||
// index := 0
|
||||
// for {
|
||||
|
||||
// opcode, arg1, arg2, arg3 := getValues(instructions, index)
|
||||
// switch opcode {
|
||||
// case 1:
|
||||
// instructions[arg3] = arg1 + arg2
|
||||
// index += 4
|
||||
// case 2:
|
||||
// instructions[arg3] = arg1 * arg2
|
||||
// index += 4
|
||||
// case 3:
|
||||
// instructions[arg1] = input
|
||||
// index += 2
|
||||
// case 4:
|
||||
// results = append(results, instructions[arg1])
|
||||
// index += 2
|
||||
// case 99:
|
||||
// fmt.Println(results)
|
||||
// os.Exit(0)
|
||||
// default:
|
||||
// fmt.Println("Invalid opcode")
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// func getValues(instructions []int, index int) (int, int, int, int) {
|
||||
|
||||
// instruction := instructions[index]
|
||||
// if instruction == 99 {
|
||||
// return instruction, 0, 0, 0
|
||||
// }
|
||||
|
||||
// opcode := instruction % 100
|
||||
|
||||
// if opcode == 3 || opcode == 4 {
|
||||
// return opcode, instructions[index+1], 0, 0
|
||||
// }
|
||||
|
||||
// // tests if opcode is 1 or 2...
|
||||
// // if inSlice([]int{1, 2}, opcode) {
|
||||
// if opcode == 1 || opcode == 2 {
|
||||
// // variables to store the values that the op code should use
|
||||
// var arg1, arg2, arg3 int
|
||||
// // arg 3 is where to write the next value to, (it's always by position)
|
||||
// arg3 = instructions[index+3]
|
||||
|
||||
// if math.Floor(float64((instruction%1000)/100)) == 1 {
|
||||
// // 1 is immediate mode
|
||||
// arg1 = instructions[index+1]
|
||||
// } else {
|
||||
// // otherwise 0 is position mode
|
||||
// arg1 = instructions[instructions[index+1]]
|
||||
// }
|
||||
// if math.Floor(float64((instruction%10000)/1000)) == 1 {
|
||||
// arg2 = instructions[index+2] // immediate
|
||||
// } else {
|
||||
// arg2 = instructions[instructions[index+2]] // position
|
||||
// }
|
||||
// // return the list of arrays
|
||||
// return opcode, arg1, arg2, arg3
|
||||
// }
|
||||
|
||||
// return opcode, 0, 0, 0
|
||||
// }
|
||||
+184
-24
@@ -1,40 +1,200 @@
|
||||
/*
|
||||
Intcode 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"
|
||||
|
||||
"adventofcode/day07/part1/intcode"
|
||||
"adventofcode/day07/part1/permutations"
|
||||
"adventofcode/util"
|
||||
)
|
||||
|
||||
// input to first amp = 0
|
||||
// output of each amp is input of next amp
|
||||
// final output is from amp #5 / E to thrusters
|
||||
func main() {
|
||||
readInput := util.ReadFile("../input.txt")
|
||||
strSplit := strings.Split(readInput, ",")
|
||||
// read the input file, modify it to a slice of numbers
|
||||
inputFile := util.ReadFile("../input.txt")
|
||||
|
||||
input := make([]int, len(strSplit))
|
||||
for i, v := range strSplit {
|
||||
input[i], _ = strconv.Atoi(v)
|
||||
splitStrings := strings.Split(inputFile, ",")
|
||||
|
||||
inputNumbers := make([]int, len(splitStrings))
|
||||
for i, v := range splitStrings {
|
||||
inputNumbers[i], _ = strconv.Atoi(v)
|
||||
}
|
||||
|
||||
// create all permutations of 0, 1, 2, 3, 4
|
||||
perms := permutations.CreatePermutations()
|
||||
// fmt.Println(perms)
|
||||
// Make perms via a util function
|
||||
perms := util.MakePermutations([]int{0, 1, 2, 3, 4})
|
||||
|
||||
highestReturn := 0
|
||||
for _, onePerm := range perms {
|
||||
lastOutput := 0
|
||||
for _, firstInput := range onePerm {
|
||||
lastOutput = intcode.RunDiagnostics(input, firstInput, lastOutput)
|
||||
}
|
||||
if lastOutput > highestReturn {
|
||||
highestReturn = lastOutput
|
||||
// iterate over all perms and run through a single pass of the Amps
|
||||
// if the final output (from Amp E) is higher, update the highestOutput variable
|
||||
highestOutput := 0
|
||||
for _, perm := range *perms {
|
||||
// initialize 5 computers
|
||||
ampA := MakeComputer(inputNumbers, perm[0])
|
||||
ampB := MakeComputer(inputNumbers, perm[1])
|
||||
ampC := MakeComputer(inputNumbers, perm[2])
|
||||
ampD := MakeComputer(inputNumbers, perm[3])
|
||||
ampE := MakeComputer(inputNumbers, perm[4])
|
||||
|
||||
// first input (besides phase setting) to Amp A is zero
|
||||
ampA.Step(0)
|
||||
ampB.Step(ampA.LastOutput)
|
||||
ampC.Step(ampB.LastOutput)
|
||||
ampD.Step(ampC.LastOutput)
|
||||
ampE.Step(ampD.LastOutput)
|
||||
|
||||
if ampE.LastOutput > highestOutput {
|
||||
highestOutput = ampE.LastOutput
|
||||
}
|
||||
}
|
||||
fmt.Println("highestReturn is", highestReturn)
|
||||
|
||||
// print highest output found
|
||||
fmt.Printf("Highest output is %v\n", highestOutput)
|
||||
}
|
||||
|
||||
/*
|
||||
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 {
|
||||
PhaseSetting int // initial input: ID or number used to "prime"/setup the comp
|
||||
PuzzleInput []int // file/puzzle input parsed into slice of ints
|
||||
InstructionIndex int // stores the index where the next instruction is
|
||||
LastOutput int // last output from an opcode 4
|
||||
}
|
||||
|
||||
// MakeComputer initializes a new comp
|
||||
func MakeComputer(PuzzleInput []int, PhaseSetting int) Intcode {
|
||||
puzzleInputCopy := make([]int, len(PuzzleInput))
|
||||
copy(puzzleInputCopy, PuzzleInput)
|
||||
|
||||
comp := Intcode{
|
||||
PhaseSetting,
|
||||
puzzleInputCopy,
|
||||
0,
|
||||
0,
|
||||
}
|
||||
|
||||
// Prime the computer by running its initial phase setting through it
|
||||
// This will update the comp's InstructionIndex so it's pointing to the next command
|
||||
// will also update the PuzzleInput itself via opcode 3's insert
|
||||
// AND will run the computer until it asks for the next input, _comp is now primed_
|
||||
comp.Step(PhaseSetting)
|
||||
return comp
|
||||
}
|
||||
|
||||
// Step will read the next 4 values in the input `sli` and make updates
|
||||
// according to the opcodes
|
||||
func (comp *Intcode) Step(input int) int {
|
||||
// read the instruction, opcode and the indexes where the params point to
|
||||
opcode, paramIndexes := comp.GetOpCodeAndIndexes()
|
||||
|
||||
switch opcode {
|
||||
case 99: // 99: Terminates program
|
||||
// fmt.Println("Terminating...")
|
||||
return input
|
||||
case 1: // 1: Add next two paramIndexes, store in third
|
||||
comp.PuzzleInput[paramIndexes[2]] = comp.PuzzleInput[paramIndexes[0]] + comp.PuzzleInput[paramIndexes[1]]
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(input)
|
||||
case 2: // 2: Multiply next two and store in third
|
||||
comp.PuzzleInput[paramIndexes[2]] = comp.PuzzleInput[paramIndexes[0]] * comp.PuzzleInput[paramIndexes[1]]
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(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 the LastOutput
|
||||
// NOTE: making a big assumption that -1 will never be an input...
|
||||
if input == -1 {
|
||||
return comp.LastOutput
|
||||
}
|
||||
|
||||
// otherwise use the input, then recurse with a -1 to signal the initial input has been used
|
||||
comp.PuzzleInput[paramIndexes[0]] = input
|
||||
comp.InstructionIndex += 2
|
||||
return comp.Step(-1)
|
||||
case 4: // 4: outputs its input value
|
||||
// set LastOutput of the computer & log it
|
||||
comp.LastOutput = comp.PuzzleInput[paramIndexes[0]]
|
||||
// fmt.Printf("Opcode 4 output: %v\n", comp.LastOutput)
|
||||
comp.InstructionIndex += 2
|
||||
|
||||
// continue running until terminates or asks for another input
|
||||
return comp.Step(input)
|
||||
// 5: jump-if-true: if first param != 0, move pointer to second param, else nothing
|
||||
case 5:
|
||||
if comp.PuzzleInput[paramIndexes[0]] != 0 {
|
||||
comp.InstructionIndex = comp.PuzzleInput[paramIndexes[1]]
|
||||
} else {
|
||||
comp.InstructionIndex += 3
|
||||
}
|
||||
return 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[paramIndexes[0]] == 0 {
|
||||
comp.InstructionIndex = comp.PuzzleInput[paramIndexes[1]]
|
||||
} else {
|
||||
comp.InstructionIndex += 3
|
||||
}
|
||||
return 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[paramIndexes[0]] < comp.PuzzleInput[paramIndexes[1]] {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 1
|
||||
} else {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 0
|
||||
}
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(input)
|
||||
// 8: equals, if param1 == param2 then set position of 3rd param to 1, else store 0
|
||||
case 8:
|
||||
if comp.PuzzleInput[paramIndexes[0]] == comp.PuzzleInput[paramIndexes[1]] {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 1
|
||||
} else {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 0
|
||||
}
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(input)
|
||||
default:
|
||||
log.Fatal("Error: unknown opcode: ", opcode)
|
||||
}
|
||||
// this should never be called b/c switch statement will always return
|
||||
return -1
|
||||
}
|
||||
|
||||
/*
|
||||
GetOpCodeAndIndexes 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) GetOpCodeAndIndexes() (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 1: // immediate mode, the index itself
|
||||
paramIndexes[i-1] = comp.InstructionIndex + i
|
||||
case 0: // position mode, index will be the value at the index
|
||||
paramIndexes[i-1] = comp.PuzzleInput[comp.InstructionIndex+i]
|
||||
}
|
||||
}
|
||||
|
||||
return opcode, paramIndexes
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package permutations
|
||||
|
||||
// CreatePermutations will return a 2D slice containing permutations from zero to the inputted int
|
||||
// func CreatePermutations(size int) [][]int {
|
||||
// result := make([][]int, 0)
|
||||
|
||||
// helper := func(digits []int, builder []int) {
|
||||
|
||||
// newDigits := make([]int, len(digits))
|
||||
// copy(newDigits, digits)
|
||||
|
||||
// if len(digits) == 0 {
|
||||
// // use the reference point in memory
|
||||
// result = append(result, builder)
|
||||
// } else {
|
||||
// for index, digit := range newDigits {
|
||||
// fmt.Println("append", append(newDigits[:index], newDigits[index+1:]...))
|
||||
// fmt.Println("builder", append(builder, digit))
|
||||
// helper(append(newDigits[:index], newDigits[index+1:]...), append(builder, digit))
|
||||
// // fmt.Println("looping")
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// helper([]int{0, 1, 2, 3, 4}, make([]int, 0))
|
||||
|
||||
// return result
|
||||
// }
|
||||
|
||||
func nextPerm(p []int) {
|
||||
for i := len(p) - 1; i >= 0; i-- {
|
||||
if i == 0 || p[i] < len(p)-i-1 {
|
||||
p[i]++
|
||||
return
|
||||
}
|
||||
p[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func getPerm(orig, p []int) []int {
|
||||
result := append([]int{}, orig...)
|
||||
for i, v := range p {
|
||||
result[i], result[i+v] = result[i+v], result[i]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CreatePermutations docz
|
||||
func CreatePermutations() [][]int {
|
||||
orig := []int{0, 1, 2, 3, 4}
|
||||
results := make([][]int, 0)
|
||||
|
||||
for p := make([]int, len(orig)); p[0] < len(p); nextPerm(p) {
|
||||
// fmt.Println(getPerm(orig, p))
|
||||
results = append(results, getPerm(orig, p))
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
package intcode
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Intcode runs the intcode computer on an inputted slice
|
||||
// func Intcode(puzzleInput []int) {
|
||||
// // default input slice, index 1 and 2 will be replaced
|
||||
// // puzzleInput := []int{3, 225, 1, 225, 6, 6, 1100, 1, 238, 225, 104, 0, 1, 192, 154, 224, 101, -161, 224, 224, 4, 224, 102, 8, 223, 223, 101, 5, 224, 224, 1, 223, 224, 223, 1001, 157, 48, 224, 1001, 224, -61, 224, 4, 224, 102, 8, 223, 223, 101, 2, 224, 224, 1, 223, 224, 223, 1102, 15, 28, 225, 1002, 162, 75, 224, 1001, 224, -600, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 1, 224, 1, 224, 223, 223, 102, 32, 57, 224, 1001, 224, -480, 224, 4, 224, 102, 8, 223, 223, 101, 1, 224, 224, 1, 224, 223, 223, 1101, 6, 23, 225, 1102, 15, 70, 224, 1001, 224, -1050, 224, 4, 224, 1002, 223, 8, 223, 101, 5, 224, 224, 1, 224, 223, 223, 101, 53, 196, 224, 1001, 224, -63, 224, 4, 224, 102, 8, 223, 223, 1001, 224, 3, 224, 1, 224, 223, 223, 1101, 64, 94, 225, 1102, 13, 23, 225, 1101, 41, 8, 225, 2, 105, 187, 224, 1001, 224, -60, 224, 4, 224, 1002, 223, 8, 223, 101, 6, 224, 224, 1, 224, 223, 223, 1101, 10, 23, 225, 1101, 16, 67, 225, 1101, 58, 10, 225, 1101, 25, 34, 224, 1001, 224, -59, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 3, 224, 1, 223, 224, 223, 4, 223, 99, 0, 0, 0, 677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1105, 0, 99999, 1105, 227, 247, 1105, 1, 99999, 1005, 227, 99999, 1005, 0, 256, 1105, 1, 99999, 1106, 227, 99999, 1106, 0, 265, 1105, 1, 99999, 1006, 0, 99999, 1006, 227, 274, 1105, 1, 99999, 1105, 1, 280, 1105, 1, 99999, 1, 225, 225, 225, 1101, 294, 0, 0, 105, 1, 0, 1105, 1, 99999, 1106, 0, 300, 1105, 1, 99999, 1, 225, 225, 225, 1101, 314, 0, 0, 106, 0, 0, 1105, 1, 99999, 1108, 226, 226, 224, 102, 2, 223, 223, 1005, 224, 329, 101, 1, 223, 223, 107, 226, 226, 224, 1002, 223, 2, 223, 1005, 224, 344, 1001, 223, 1, 223, 107, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 359, 101, 1, 223, 223, 7, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 374, 101, 1, 223, 223, 108, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 389, 101, 1, 223, 223, 1007, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 404, 101, 1, 223, 223, 7, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 419, 101, 1, 223, 223, 1107, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 434, 1001, 223, 1, 223, 1108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 449, 101, 1, 223, 223, 108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 464, 1001, 223, 1, 223, 8, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 479, 1001, 223, 1, 223, 1007, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 494, 101, 1, 223, 223, 1008, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 509, 101, 1, 223, 223, 1107, 677, 226, 224, 1002, 223, 2, 223, 1006, 224, 524, 1001, 223, 1, 223, 108, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 539, 1001, 223, 1, 223, 1107, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 554, 1001, 223, 1, 223, 7, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 569, 1001, 223, 1, 223, 8, 677, 226, 224, 102, 2, 223, 223, 1006, 224, 584, 101, 1, 223, 223, 1008, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 599, 101, 1, 223, 223, 1007, 226, 677, 224, 1002, 223, 2, 223, 1006, 224, 614, 1001, 223, 1, 223, 8, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 629, 101, 1, 223, 223, 107, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 644, 101, 1, 223, 223, 1108, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 659, 101, 1, 223, 223, 1008, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 674, 1001, 223, 1, 223, 4, 223, 99, 226}
|
||||
|
||||
// // Part 1: ID of System is 1 (use as the input)
|
||||
// // runDiagnostics(puzzleInput, 1)
|
||||
|
||||
// // Part 2: ID of System is 5 (use as the input)
|
||||
// RunDiagnostics(puzzleInput, 0)
|
||||
// }
|
||||
|
||||
// RunDiagnostics runs the entire computer on a puzzleInput and an inputValue
|
||||
// three returned ints will be
|
||||
// 1. the index that the intcode compiler stopped on
|
||||
// 2. the code that triggered the "exit"
|
||||
// 3. the output
|
||||
func RunDiagnostics(puzzleInput []int, inputValue, index int) (int, int, int) {
|
||||
// store the lastOutputValue to be returned upon a 99
|
||||
var lastOutputValue int
|
||||
secondInputFlag := false
|
||||
|
||||
for i := index; i < len(puzzleInput); {
|
||||
// find op code (last 2 digits of number), a 1, 2, 3, 4, or 99
|
||||
// find param1 and param2 which are the 100's and 1000's digit in the i-th element
|
||||
opCode, param1, param2, _ := returnCodes(puzzleInput[i])
|
||||
var firstVal, secondVal, thirdVal int
|
||||
|
||||
// set value variables based on what the opCodes are (some of them will throw errors if I attempt to set them...)
|
||||
if opCode == 1 || opCode == 2 || opCode == 7 || opCode == 8 {
|
||||
firstVal, secondVal = getValue(puzzleInput, param1, puzzleInput[i+1]), getValue(puzzleInput, param2, puzzleInput[i+2])
|
||||
thirdVal = puzzleInput[i+3]
|
||||
} else if opCode == 3 || opCode == 4 {
|
||||
firstVal = puzzleInput[i+1]
|
||||
} else if opCode == 5 || opCode == 6 {
|
||||
firstVal, secondVal = getValue(puzzleInput, param1, puzzleInput[i+1]), getValue(puzzleInput, param2, puzzleInput[i+2])
|
||||
}
|
||||
|
||||
// switch statement to handle the opcode value
|
||||
switch opCode {
|
||||
case 99:
|
||||
// fmt.Println("99 halts IntCode instance")
|
||||
return i, 99, lastOutputValue
|
||||
case 1:
|
||||
// add and place (by position)
|
||||
// firstToAdd, secondToAdd := getValue(puzzleInput, param1, puzzleInput[i+1]), getValue(puzzleInput, param2, puzzleInput[i+2])
|
||||
puzzleInput[thirdVal] = firstVal + secondVal
|
||||
i += 4
|
||||
case 2:
|
||||
// multiply and place (by position)
|
||||
puzzleInput[thirdVal] = firstVal * secondVal
|
||||
i += 4
|
||||
case 3:
|
||||
// i need some kind of flag here to hold if there is a second input being asked for in the same call...
|
||||
if secondInputFlag {
|
||||
// fmt.Println("results from second input return", i, lastOutputValue)
|
||||
return i, 3, lastOutputValue
|
||||
}
|
||||
secondInputFlag = true
|
||||
|
||||
// fmt.Println("--INPUT OPCODE 3")
|
||||
// write inputValue to puzzle input by position
|
||||
puzzleInput[firstVal] = inputValue
|
||||
|
||||
i += 2
|
||||
case 4:
|
||||
// output the value to the console, always by position
|
||||
// fmt.Println("output: ", puzzleInput[firstVal])
|
||||
lastOutputValue = puzzleInput[firstVal]
|
||||
i += 2
|
||||
// return the index (to pass back in, a 4 to signal that it was not a halt, and the outputted value)
|
||||
return i, 4, lastOutputValue
|
||||
case 5:
|
||||
// jump-if-true
|
||||
// if first param is != 0 set instruction pointer to value from second parameter
|
||||
if firstVal != 0 {
|
||||
// fmt.Println("5 moves i to", secondVal)
|
||||
i = secondVal
|
||||
} else {
|
||||
// otherwise do nothing except increment i
|
||||
// increment by 3 (like opCode 6)
|
||||
i += 3
|
||||
}
|
||||
case 6:
|
||||
// jump-if-false
|
||||
// if first param is != 0 set instruction pointer to value from second parameter
|
||||
if firstVal == 0 {
|
||||
i = secondVal
|
||||
} else {
|
||||
// otherwise increment i to the next instruction
|
||||
// this instruction has 3 values, so i increments by 3
|
||||
i += 3
|
||||
}
|
||||
case 7:
|
||||
// less than - if firstVal < secondVal, store a 1 @ position of thirdVal, otherwise store a 0
|
||||
if firstVal < secondVal {
|
||||
puzzleInput[thirdVal] = 1
|
||||
} else {
|
||||
puzzleInput[thirdVal] = 0
|
||||
}
|
||||
i += 4
|
||||
case 8:
|
||||
// equals, same as opCode 7 but conditional is firstVal is equal to secondVal
|
||||
if firstVal == secondVal {
|
||||
puzzleInput[thirdVal] = 1
|
||||
} else {
|
||||
puzzleInput[thirdVal] = 0
|
||||
}
|
||||
i += 4
|
||||
default:
|
||||
fmt.Println("bad opCode!!! returning -999")
|
||||
return 0, 0, -999
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("shouldn't have reached end of function, returning -1000")
|
||||
return 0, 0, -1000
|
||||
}
|
||||
|
||||
func returnCodes(number int) (int, int, int, int) {
|
||||
return number % 100, (number % 1000) / 100, (number % 10000) / 1000, (number % 100000) / 10000
|
||||
}
|
||||
|
||||
func getValue(puzzleInput []int, positionOrImmediateCode int, nextOrTwoPastValue int) int {
|
||||
// read if the param is for position or immediate mode and return the value (to be added or multiplied)
|
||||
if positionOrImmediateCode == 0 {
|
||||
// 0 is position mode
|
||||
return puzzleInput[nextOrTwoPastValue]
|
||||
}
|
||||
// otherwise it's immediate mode (no-else-return)
|
||||
return nextOrTwoPastValue
|
||||
}
|
||||
|
||||
// note: a solution to part 1 that I looked up to get some insight into golang
|
||||
// package main
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "math"
|
||||
// "os"
|
||||
// )
|
||||
|
||||
// func main() {
|
||||
|
||||
// // var instructionStrings []string
|
||||
// var results []int
|
||||
// // input := 1
|
||||
|
||||
// // file, err := os.Open("./input.txt")
|
||||
// // if err != nil {
|
||||
// // log.Fatal(err)
|
||||
// // }
|
||||
// // defer file.Close()
|
||||
|
||||
// // scanner := bufio.NewScanner(file)
|
||||
// // for scanner.Scan() {
|
||||
// // line := scanner.Text()
|
||||
// // instructionStrings = strings.Split(line, ",")
|
||||
// // }
|
||||
|
||||
// // instructions := make([]int, len(instructionStrings))
|
||||
|
||||
// // for i, v := range instructionStrings {
|
||||
// // instructions[i], _ = strconv.Atoi(v)
|
||||
// // }
|
||||
|
||||
// // note pasted in instructions slice
|
||||
// instructions := []int{3, 225, 1, 225, 6, 6, 1100, 1, 238, 225, 104, 0, 1, 192, 154, 224, 101, -161, 224, 224, 4, 224, 102, 8, 223, 223, 101, 5, 224, 224, 1, 223, 224, 223, 1001, 157, 48, 224, 1001, 224, -61, 224, 4, 224, 102, 8, 223, 223, 101, 2, 224, 224, 1, 223, 224, 223, 1102, 15, 28, 225, 1002, 162, 75, 224, 1001, 224, -600, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 1, 224, 1, 224, 223, 223, 102, 32, 57, 224, 1001, 224, -480, 224, 4, 224, 102, 8, 223, 223, 101, 1, 224, 224, 1, 224, 223, 223, 1101, 6, 23, 225, 1102, 15, 70, 224, 1001, 224, -1050, 224, 4, 224, 1002, 223, 8, 223, 101, 5, 224, 224, 1, 224, 223, 223, 101, 53, 196, 224, 1001, 224, -63, 224, 4, 224, 102, 8, 223, 223, 1001, 224, 3, 224, 1, 224, 223, 223, 1101, 64, 94, 225, 1102, 13, 23, 225, 1101, 41, 8, 225, 2, 105, 187, 224, 1001, 224, -60, 224, 4, 224, 1002, 223, 8, 223, 101, 6, 224, 224, 1, 224, 223, 223, 1101, 10, 23, 225, 1101, 16, 67, 225, 1101, 58, 10, 225, 1101, 25, 34, 224, 1001, 224, -59, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 3, 224, 1, 223, 224, 223, 4, 223, 99, 0, 0, 0, 677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1105, 0, 99999, 1105, 227, 247, 1105, 1, 99999, 1005, 227, 99999, 1005, 0, 256, 1105, 1, 99999, 1106, 227, 99999, 1106, 0, 265, 1105, 1, 99999, 1006, 0, 99999, 1006, 227, 274, 1105, 1, 99999, 1105, 1, 280, 1105, 1, 99999, 1, 225, 225, 225, 1101, 294, 0, 0, 105, 1, 0, 1105, 1, 99999, 1106, 0, 300, 1105, 1, 99999, 1, 225, 225, 225, 1101, 314, 0, 0, 106, 0, 0, 1105, 1, 99999, 1108, 226, 226, 224, 102, 2, 223, 223, 1005, 224, 329, 101, 1, 223, 223, 107, 226, 226, 224, 1002, 223, 2, 223, 1005, 224, 344, 1001, 223, 1, 223, 107, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 359, 101, 1, 223, 223, 7, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 374, 101, 1, 223, 223, 108, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 389, 101, 1, 223, 223, 1007, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 404, 101, 1, 223, 223, 7, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 419, 101, 1, 223, 223, 1107, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 434, 1001, 223, 1, 223, 1108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 449, 101, 1, 223, 223, 108, 226, 677, 224, 102, 2, 223, 223, 1005, 224, 464, 1001, 223, 1, 223, 8, 226, 677, 224, 1002, 223, 2, 223, 1005, 224, 479, 1001, 223, 1, 223, 1007, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 494, 101, 1, 223, 223, 1008, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 509, 101, 1, 223, 223, 1107, 677, 226, 224, 1002, 223, 2, 223, 1006, 224, 524, 1001, 223, 1, 223, 108, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 539, 1001, 223, 1, 223, 1107, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 554, 1001, 223, 1, 223, 7, 226, 226, 224, 1002, 223, 2, 223, 1006, 224, 569, 1001, 223, 1, 223, 8, 677, 226, 224, 102, 2, 223, 223, 1006, 224, 584, 101, 1, 223, 223, 1008, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 599, 101, 1, 223, 223, 1007, 226, 677, 224, 1002, 223, 2, 223, 1006, 224, 614, 1001, 223, 1, 223, 8, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 629, 101, 1, 223, 223, 107, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 644, 101, 1, 223, 223, 1108, 677, 226, 224, 102, 2, 223, 223, 1005, 224, 659, 101, 1, 223, 223, 1008, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 674, 1001, 223, 1, 223, 4, 223, 99, 226}
|
||||
// input := 1
|
||||
|
||||
// index := 0
|
||||
// for {
|
||||
|
||||
// opcode, arg1, arg2, arg3 := getValues(instructions, index)
|
||||
// switch opcode {
|
||||
// case 1:
|
||||
// instructions[arg3] = arg1 + arg2
|
||||
// index += 4
|
||||
// case 2:
|
||||
// instructions[arg3] = arg1 * arg2
|
||||
// index += 4
|
||||
// case 3:
|
||||
// instructions[arg1] = input
|
||||
// index += 2
|
||||
// case 4:
|
||||
// results = append(results, instructions[arg1])
|
||||
// index += 2
|
||||
// case 99:
|
||||
// fmt.Println(results)
|
||||
// os.Exit(0)
|
||||
// default:
|
||||
// fmt.Println("Invalid opcode")
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// func getValues(instructions []int, index int) (int, int, int, int) {
|
||||
|
||||
// instruction := instructions[index]
|
||||
// if instruction == 99 {
|
||||
// return instruction, 0, 0, 0
|
||||
// }
|
||||
|
||||
// opcode := instruction % 100
|
||||
|
||||
// if opcode == 3 || opcode == 4 {
|
||||
// return opcode, instructions[index+1], 0, 0
|
||||
// }
|
||||
|
||||
// // tests if opcode is 1 or 2...
|
||||
// // if inSlice([]int{1, 2}, opcode) {
|
||||
// if opcode == 1 || opcode == 2 {
|
||||
// // variables to store the values that the op code should use
|
||||
// var arg1, arg2, arg3 int
|
||||
// // arg 3 is where to write the next value to, (it's always by position)
|
||||
// arg3 = instructions[index+3]
|
||||
|
||||
// if math.Floor(float64((instruction%1000)/100)) == 1 {
|
||||
// // 1 is immediate mode
|
||||
// arg1 = instructions[index+1]
|
||||
// } else {
|
||||
// // otherwise 0 is position mode
|
||||
// arg1 = instructions[instructions[index+1]]
|
||||
// }
|
||||
// if math.Floor(float64((instruction%10000)/1000)) == 1 {
|
||||
// arg2 = instructions[index+2] // immediate
|
||||
// } else {
|
||||
// arg2 = instructions[instructions[index+2]] // position
|
||||
// }
|
||||
// // return the list of arrays
|
||||
// return opcode, arg1, arg2, arg3
|
||||
// }
|
||||
|
||||
// return opcode, 0, 0, 0
|
||||
// }
|
||||
@@ -1,23 +0,0 @@
|
||||
function makePerms(low, high) {
|
||||
const digits = [];
|
||||
for (let i = low; i <= high; i++) {
|
||||
digits.push(i);
|
||||
}
|
||||
|
||||
const allPerms = [];
|
||||
|
||||
function inner(digitsArr, perm = []) {
|
||||
if (perm.length === 5) {
|
||||
allPerms.push(perm);
|
||||
} else {
|
||||
digitsArr.forEach((digit, index) => {
|
||||
inner(digitsArr.slice(0, index).concat(digitsArr.slice(index + 1)), perm.concat(digit))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
inner(digits);
|
||||
return allPerms;
|
||||
}
|
||||
|
||||
console.log(makePerms(0, 4));
|
||||
+191
-73
@@ -1,89 +1,207 @@
|
||||
/*
|
||||
Intcode struct is defined within this file
|
||||
MakePermutations is in the util package as that will likely be reused
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"adventofcode/util"
|
||||
"fmt"
|
||||
|
||||
"./intcode"
|
||||
"./permutations"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// input to first amp = 0
|
||||
// output of each amp is input of next amp
|
||||
// final output is from amp #5 / E to thrusters
|
||||
// read the input file, modify it to a slice of numbers
|
||||
inputFile := util.ReadFile("../input.txt")
|
||||
|
||||
input := []int{3, 8, 1001, 8, 10, 8, 105, 1, 0, 0, 21, 42, 55, 64, 77, 94, 175, 256, 337, 418, 99999, 3, 9, 102, 4, 9, 9, 1001, 9, 5, 9, 102, 2, 9, 9, 101, 3, 9, 9, 4, 9, 99, 3, 9, 102, 2, 9, 9, 101, 5, 9, 9, 4, 9, 99, 3, 9, 1002, 9, 4, 9, 4, 9, 99, 3, 9, 102, 4, 9, 9, 101, 5, 9, 9, 4, 9, 99, 3, 9, 102, 5, 9, 9, 1001, 9, 3, 9, 1002, 9, 5, 9, 4, 9, 99, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1001, 9, 1, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 101, 2, 9, 9, 4, 9, 3, 9, 1001, 9, 2, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 99, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 1001, 9, 2, 9, 4, 9, 3, 9, 1001, 9, 1, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 101, 2, 9, 9, 4, 9, 3, 9, 1001, 9, 1, 9, 4, 9, 3, 9, 1001, 9, 1, 9, 4, 9, 99, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 101, 2, 9, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 1001, 9, 2, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 99, 3, 9, 101, 2, 9, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 1001, 9, 2, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 1001, 9, 2, 9, 4, 9, 3, 9, 101, 2, 9, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 99, 3, 9, 1001, 9, 2, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 102, 2, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 101, 1, 9, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 1002, 9, 2, 9, 4, 9, 3, 9, 1001, 9, 1, 9, 4, 9, 99}
|
||||
splitStrings := strings.Split(inputFile, ",")
|
||||
|
||||
// should give 18216
|
||||
// input := []int{3, 52, 1001, 52, -5, 52, 3, 53, 1, 52, 56, 54, 1007, 54, 5, 55, 1005, 55, 26, 1001, 54, -5, 54, 1105, 1, 12, 1, 53, 54, 53, 1008, 54, 0, 55, 1001, 55, 1, 55, 2, 53, 55, 53, 4, 53, 1001, 56, -1, 56, 1005, 56, 6, 99, 0, 0, 0, 0, 10}
|
||||
|
||||
// create all permutations of 5, 6, 7, 8, 9
|
||||
perms := permutations.CreatePermutations(5, 9)
|
||||
// fmt.Println(perms)
|
||||
|
||||
// will be the final returned value
|
||||
var highestReturn int
|
||||
|
||||
// loop over all of the permutations
|
||||
for _, onePerm := range perms {
|
||||
// needs to have the right length to copy into
|
||||
input1 := make([]int, len(input))
|
||||
input2 := make([]int, len(input))
|
||||
input3 := make([]int, len(input))
|
||||
input4 := make([]int, len(input))
|
||||
input5 := make([]int, len(input))
|
||||
|
||||
// make copies of the input, one for each thruster
|
||||
copy(input1, input)
|
||||
copy(input2, input)
|
||||
copy(input3, input)
|
||||
copy(input4, input)
|
||||
copy(input5, input)
|
||||
|
||||
// fmt.Println(input1)
|
||||
// fmt.Println(onePerm)
|
||||
|
||||
// This will be the final thruster signal, and we want to return the maximum one
|
||||
var last5Return int // zero nil value!
|
||||
|
||||
// Initial load for the permutation of 5-9
|
||||
index1, _, lastOutput1 := intcode.RunDiagnostics(input1, onePerm[0], 0)
|
||||
index2, _, lastOutput2 := intcode.RunDiagnostics(input2, onePerm[1], 0)
|
||||
index3, _, lastOutput3 := intcode.RunDiagnostics(input3, onePerm[2], 0)
|
||||
index4, _, lastOutput4 := intcode.RunDiagnostics(input4, onePerm[3], 0)
|
||||
index5, exitCode5, lastOutput5 := intcode.RunDiagnostics(input5, onePerm[4], 0)
|
||||
// fmt.Println("INITIAL LOADS DONE"
|
||||
|
||||
// Here's the fix to my problem:
|
||||
// I needed to account for the initial load but then also the second input coming from the preceeding Amp thingy
|
||||
// But because this is the exact same code as the loop below, I've commented it out
|
||||
// index1, _, lastOutput1 = intcode.RunDiagnostics(input1, lastOutput5, index1)
|
||||
// index2, _, lastOutput2 = intcode.RunDiagnostics(input2, lastOutput1, index2)
|
||||
// index3, _, lastOutput3 = intcode.RunDiagnostics(input3, lastOutput2, index3)
|
||||
// index4, _, lastOutput4 = intcode.RunDiagnostics(input4, lastOutput3, index4)
|
||||
// index5, _, lastOutput5 = intcode.RunDiagnostics(input5, lastOutput4, index5)
|
||||
// fmt.Println("Second input load done")
|
||||
|
||||
for exitCode5 != 99 {
|
||||
index1, _, lastOutput1 = intcode.RunDiagnostics(input1, lastOutput5, index1)
|
||||
index2, _, lastOutput2 = intcode.RunDiagnostics(input2, lastOutput1, index2)
|
||||
index3, _, lastOutput3 = intcode.RunDiagnostics(input3, lastOutput2, index3)
|
||||
index4, _, lastOutput4 = intcode.RunDiagnostics(input4, lastOutput3, index4)
|
||||
index5, exitCode5, lastOutput5 = intcode.RunDiagnostics(input5, lastOutput4, index5)
|
||||
if exitCode5 == 4 {
|
||||
last5Return = lastOutput5
|
||||
} else if exitCode5 == 99 {
|
||||
// fmt.Println("99 exit code!", lastOutput5) // loop will end now
|
||||
inputNumbers := make([]int, len(splitStrings))
|
||||
for i, v := range splitStrings {
|
||||
fmt.Println(v)
|
||||
inputNumbers[i], _ = strconv.Atoi(v)
|
||||
}
|
||||
// fmt.Println("one full pass") // using this to check if multiple inputs are being asked for
|
||||
fmt.Println(inputNumbers)
|
||||
// Make perms via a util function
|
||||
perms := util.MakePermutations([]int{5, 6, 7, 8, 9})
|
||||
|
||||
// iterate over all perms and run through a single pass of the Amps
|
||||
// if the final output (from Amp E) is higher, update the highestOutput variable
|
||||
highestOutput := 0
|
||||
for _, perm := range *perms {
|
||||
// initialize 5 computers
|
||||
ampA := MakeComputer(inputNumbers, perm[0])
|
||||
ampB := MakeComputer(inputNumbers, perm[1])
|
||||
ampC := MakeComputer(inputNumbers, perm[2])
|
||||
ampD := MakeComputer(inputNumbers, perm[3])
|
||||
ampE := MakeComputer(inputNumbers, perm[4])
|
||||
|
||||
// Iterate while the Amps are still running (i.e. not terminated)
|
||||
for ampA.IsRunning && ampB.IsRunning && ampC.IsRunning && ampD.IsRunning && ampE.IsRunning {
|
||||
// first input to Amp A is a zero, this is the zero-value of an int!
|
||||
ampA.Step(ampE.LastOutput)
|
||||
ampB.Step(ampA.LastOutput)
|
||||
ampC.Step(ampB.LastOutput)
|
||||
ampD.Step(ampC.LastOutput)
|
||||
ampE.Step(ampD.LastOutput)
|
||||
}
|
||||
|
||||
// fmt.Println(lastOutput5) // should be changing for each perm
|
||||
if ampE.LastOutput > highestOutput {
|
||||
highestOutput = ampE.LastOutput
|
||||
}
|
||||
}
|
||||
|
||||
// check if the max thrust input is higher than highest return
|
||||
if last5Return > highestReturn {
|
||||
highestReturn = last5Return
|
||||
// print highest output found
|
||||
fmt.Printf("Highest output is %v\n", highestOutput)
|
||||
}
|
||||
|
||||
/*
|
||||
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 {
|
||||
PhaseSetting int // initial input: ID or number used to "prime"/setup the comp
|
||||
PuzzleInput []int // file/puzzle input parsed into slice of ints
|
||||
InstructionIndex int // stores the index where the next instruction is
|
||||
LastOutput int // last output from an opcode 4
|
||||
IsRunning bool // will be true until a 99 opcode is hit
|
||||
}
|
||||
|
||||
// MakeComputer initializes a new comp
|
||||
func MakeComputer(PuzzleInput []int, PhaseSetting int) Intcode {
|
||||
puzzleInputCopy := make([]int, len(PuzzleInput))
|
||||
copy(puzzleInputCopy, PuzzleInput)
|
||||
|
||||
comp := Intcode{
|
||||
PhaseSetting,
|
||||
puzzleInputCopy,
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
}
|
||||
|
||||
// Prime the computer by running its initial phase setting through it
|
||||
// This will update the comp's InstructionIndex so it's pointing to the next command
|
||||
// will also update the PuzzleInput itself via opcode 3's insert
|
||||
// AND will run the computer until it asks for the next input, _comp is now primed_
|
||||
comp.Step(PhaseSetting)
|
||||
return comp
|
||||
}
|
||||
|
||||
// Step will read the next 4 values in the input `sli` and make updates
|
||||
// according to the opcodes
|
||||
func (comp *Intcode) Step(input int) int {
|
||||
// read the instruction, opcode and the indexes where the params point to
|
||||
opcode, paramIndexes := comp.GetOpCodeAndIndexes()
|
||||
|
||||
switch opcode {
|
||||
case 99: // 99: Terminates program
|
||||
fmt.Println("Terminating...")
|
||||
comp.IsRunning = false
|
||||
return input
|
||||
case 1: // 1: Add next two paramIndexes, store in third
|
||||
comp.PuzzleInput[paramIndexes[2]] = comp.PuzzleInput[paramIndexes[0]] + comp.PuzzleInput[paramIndexes[1]]
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(input)
|
||||
case 2: // 2: Multiply next two and store in third
|
||||
comp.PuzzleInput[paramIndexes[2]] = comp.PuzzleInput[paramIndexes[0]] * comp.PuzzleInput[paramIndexes[1]]
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(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 the LastOutput
|
||||
// NOTE: making a big assumption that -1 will never be an input...
|
||||
if input == -1 {
|
||||
return comp.LastOutput
|
||||
}
|
||||
|
||||
// otherwise use the input, then recurse with a -1 to signal the initial input has been used
|
||||
comp.PuzzleInput[paramIndexes[0]] = input
|
||||
comp.InstructionIndex += 2
|
||||
return comp.Step(-1)
|
||||
case 4: // 4: outputs its input value
|
||||
// set LastOutput of the computer & log it
|
||||
comp.LastOutput = comp.PuzzleInput[paramIndexes[0]]
|
||||
// fmt.Printf("Opcode 4 output: %v\n", comp.LastOutput)
|
||||
comp.InstructionIndex += 2
|
||||
|
||||
// continue running until terminates or asks for another input
|
||||
return comp.Step(input)
|
||||
// 5: jump-if-true: if first param != 0, move pointer to second param, else nothing
|
||||
case 5:
|
||||
if comp.PuzzleInput[paramIndexes[0]] != 0 {
|
||||
comp.InstructionIndex = comp.PuzzleInput[paramIndexes[1]]
|
||||
} else {
|
||||
comp.InstructionIndex += 3
|
||||
}
|
||||
return 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[paramIndexes[0]] == 0 {
|
||||
comp.InstructionIndex = comp.PuzzleInput[paramIndexes[1]]
|
||||
} else {
|
||||
comp.InstructionIndex += 3
|
||||
}
|
||||
return 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[paramIndexes[0]] < comp.PuzzleInput[paramIndexes[1]] {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 1
|
||||
} else {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 0
|
||||
}
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(input)
|
||||
// 8: equals, if param1 == param2 then set position of 3rd param to 1, else store 0
|
||||
case 8:
|
||||
if comp.PuzzleInput[paramIndexes[0]] == comp.PuzzleInput[paramIndexes[1]] {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 1
|
||||
} else {
|
||||
comp.PuzzleInput[paramIndexes[2]] = 0
|
||||
}
|
||||
comp.InstructionIndex += 4
|
||||
return comp.Step(input)
|
||||
default:
|
||||
log.Fatal("Error: unknown opcode: ", opcode)
|
||||
}
|
||||
// this should never be called b/c switch statement will always return
|
||||
return -1
|
||||
}
|
||||
|
||||
/*
|
||||
GetOpCodeAndIndexes 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) GetOpCodeAndIndexes() (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 1: // immediate mode, the index itself
|
||||
paramIndexes[i-1] = comp.InstructionIndex + i
|
||||
case 0: // position mode, index will be the value at the index
|
||||
paramIndexes[i-1] = comp.PuzzleInput[comp.InstructionIndex+i]
|
||||
}
|
||||
}
|
||||
fmt.Println("highestReturn is", highestReturn)
|
||||
|
||||
return opcode, paramIndexes
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
package permutations
|
||||
|
||||
// CreatePermutations docz
|
||||
func CreatePermutations(start, end int) [][]int {
|
||||
orig := make([]int, end-start+1)
|
||||
for i := start; i <= end; i++ {
|
||||
orig[i-start] = i
|
||||
}
|
||||
results := make([][]int, 0)
|
||||
resPointer := &results
|
||||
perm(resPointer, orig, 0)
|
||||
|
||||
// fmt.Println(len(results)) // 120 = 5!
|
||||
return results
|
||||
}
|
||||
|
||||
func perm(resPointer *[][]int, slice []int, index int) {
|
||||
if index == len(slice) {
|
||||
*resPointer = append(*resPointer, slice)
|
||||
// fmt.Println("appending", resPointer)
|
||||
} else {
|
||||
temp := slice[index]
|
||||
for i := index; i < len(slice); i++ {
|
||||
newSlice := make([]int, len(slice))
|
||||
copy(newSlice, slice)
|
||||
// fmt.Println(newSlice, slice)
|
||||
newSlice[index] = newSlice[i]
|
||||
newSlice[i] = temp
|
||||
perm(resPointer, newSlice, index+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePermutations will return a 2D slice containing permutations from zero to the inputted int
|
||||
// func CreatePermutations(size int) [][]int {
|
||||
// result := make([][]int, 0)
|
||||
|
||||
// helper := func(digits []int, builder []int) {
|
||||
|
||||
// newDigits := make([]int, len(digits))
|
||||
// copy(newDigits, digits)
|
||||
|
||||
// if len(digits) == 0 {
|
||||
// // use the reference point in memory
|
||||
// result = append(result, builder)
|
||||
// } else {
|
||||
// for index, digit := range newDigits {
|
||||
// fmt.Println("append", append(newDigits[:index], newDigits[index+1:]...))
|
||||
// fmt.Println("builder", append(builder, digit))
|
||||
// helper(append(newDigits[:index], newDigits[index+1:]...), append(builder, digit))
|
||||
// // fmt.Println("looping")
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// helper([]int{0, 1, 2, 3, 4}, make([]int, 0))
|
||||
|
||||
// return result
|
||||
// }
|
||||
|
||||
// func nextPerm(p []int) {
|
||||
// for i := len(p) - 1; i >= 0; i-- {
|
||||
// if i == 0 || p[i] < len(p)-i-1 {
|
||||
// p[i]++
|
||||
// return
|
||||
// }
|
||||
// p[i] = 0
|
||||
// }
|
||||
// }
|
||||
|
||||
// func getPerm(orig, p []int) []int {
|
||||
// result := append([]int{}, orig...)
|
||||
// for i, v := range p {
|
||||
// result[i], result[i+v] = result[i+v], result[i]
|
||||
// }
|
||||
// return result
|
||||
// }
|
||||
|
||||
// CreatePermutations docz
|
||||
// func CreatePermutations() [][]int {
|
||||
// orig := []int{5, 6, 7, 8, 9}
|
||||
// results := make([][]int, 0)
|
||||
|
||||
// for p := make([]int, len(orig)); p[0] < len(p); nextPerm(p) {
|
||||
// // fmt.Println(getPerm(orig, p))
|
||||
// results = append(results, getPerm(orig, p))
|
||||
// }
|
||||
// return results
|
||||
// }
|
||||
@@ -0,0 +1,34 @@
|
||||
package util
|
||||
|
||||
// MakePermutations will make all permutations of the numbers input
|
||||
// returns a pointer to avoid copying a large number of permutations
|
||||
func MakePermutations(numbers []int) *[][]int {
|
||||
result := make([][]int, 0)
|
||||
|
||||
swapRecurseBacktrack(numbers, 0, &result)
|
||||
|
||||
return &result
|
||||
}
|
||||
|
||||
// helper function to generate permutations
|
||||
func swapRecurseBacktrack(numbers []int, startIndex int, results *[][]int) {
|
||||
if startIndex == len(numbers) {
|
||||
// make a copy of the perm
|
||||
perm := make([]int, len(numbers))
|
||||
copy(perm, numbers)
|
||||
|
||||
// assign the value at the pointer results to the appended slice (dereferenced) results w/ perm
|
||||
*results = append(*results, perm)
|
||||
}
|
||||
|
||||
for i := startIndex; i < len(numbers); i++ {
|
||||
// swap numbers
|
||||
numbers[startIndex], numbers[i] = numbers[i], numbers[startIndex]
|
||||
|
||||
// recurse with startIndex incremented
|
||||
swapRecurseBacktrack(numbers, startIndex+1, results)
|
||||
|
||||
// backtrack
|
||||
numbers[startIndex], numbers[i] = numbers[i], numbers[startIndex]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user