mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
117 lines
3.5 KiB
Go
117 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"github.com/alexchao26/advent-of-code-go/util"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
// read the input file, modify it to a slice of numbers
|
|
inputFile := util.ReadFile("../input.txt")
|
|
// inputFile := "3,3,1107,-1,8,3,4,3,99"
|
|
|
|
splitStrings := strings.Split(inputFile, ",")
|
|
|
|
inputNumbers := make([]int, len(splitStrings))
|
|
for i, v := range splitStrings {
|
|
inputNumbers[i], _ = strconv.Atoi(v)
|
|
}
|
|
|
|
// system ID is 5, that is the input to the intcode computer
|
|
input := 5
|
|
step(inputNumbers, 0, input)
|
|
}
|
|
|
|
// step will read the next 4 values in the input `sli` and make updates
|
|
// according to the opcodes
|
|
func step(sli []int, index, input int) int {
|
|
// read the instruction, opcode and the indexes where the params point to
|
|
opcode, paramIndexes := getOpCodeAndIndexes(sli, index)
|
|
|
|
var output int
|
|
switch opcode {
|
|
case 99: // 99: Terminates program
|
|
fmt.Println("Terminating...")
|
|
return input
|
|
case 1: // 1: Add next two paramIndexes, store in third
|
|
sli[paramIndexes[2]] = sli[paramIndexes[0]] + sli[paramIndexes[1]]
|
|
return step(sli, index+4, output)
|
|
case 2: // 2: Multiply next two and store in third
|
|
sli[paramIndexes[2]] = sli[paramIndexes[0]] * sli[paramIndexes[1]]
|
|
return step(sli, index+4, output)
|
|
case 3: // 3: Takes one input and saves it to position of one parameter
|
|
sli[paramIndexes[0]] = input
|
|
return step(sli, index+2, output)
|
|
case 4: // 4: outputs its input value
|
|
output = sli[paramIndexes[0]]
|
|
fmt.Printf("Opcode 4 output: %v\n", output)
|
|
return step(sli, index+2, output)
|
|
// 5: jump-if-true: if first param != 0, move pointer to second param, else nothing
|
|
case 5:
|
|
if sli[paramIndexes[0]] != 0 {
|
|
return step(sli, sli[paramIndexes[1]], output)
|
|
}
|
|
return step(sli, index+3, output)
|
|
// 6: jump-if-false, if first param == 0 then set instruction pointer to 2nd param, else nothing
|
|
case 6:
|
|
if sli[paramIndexes[0]] == 0 {
|
|
return step(sli, sli[paramIndexes[1]], output)
|
|
}
|
|
return step(sli, index+3, output)
|
|
// 7: less-than, if param1 < param2 then store 1 in postion of 3rd param, else store 0
|
|
case 7:
|
|
if sli[paramIndexes[0]] < sli[paramIndexes[1]] {
|
|
sli[paramIndexes[2]] = 1
|
|
} else {
|
|
sli[paramIndexes[2]] = 0
|
|
}
|
|
return step(sli, index+4, output)
|
|
// 8: equals, if param1 == param2 then set position of 3rd param to 1, else store 0
|
|
case 8:
|
|
if sli[paramIndexes[0]] == sli[paramIndexes[1]] {
|
|
sli[paramIndexes[2]] = 1
|
|
} else {
|
|
sli[paramIndexes[2]] = 0
|
|
}
|
|
return step(sli, index+4, output)
|
|
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 sli[index]
|
|
- 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 getOpCodeAndIndexes(sli []int, index int) (int, [3]int) {
|
|
instruction := sli[index]
|
|
|
|
// 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 && index+i < len(sli); 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] = index + i
|
|
case 0: // position mode, index will be the value at the index
|
|
paramIndexes[i-1] = sli[index+i]
|
|
}
|
|
}
|
|
|
|
return opcode, paramIndexes
|
|
}
|