aboutsummaryrefslogtreecommitdiff
path: root/2019/go/day09.go
diff options
context:
space:
mode:
Diffstat (limited to '2019/go/day09.go')
-rw-r--r--2019/go/day09.go166
1 files changed, 166 insertions, 0 deletions
diff --git a/2019/go/day09.go b/2019/go/day09.go
new file mode 100644
index 0000000..432d780
--- /dev/null
+++ b/2019/go/day09.go
@@ -0,0 +1,166 @@
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+)
+
+func main() {
+ var memory []int
+ start, size := 0, 0
+ if len(os.Args) < 2 {
+ panic("runtime error: missing operand")
+ }
+ file, err := ioutil.ReadFile(os.Args[1])
+ if err != nil {
+ panic(err)
+ }
+ for i := 0; i < len(file); i++ {
+ if file[i] == ',' || file[i] == '\n' {
+ arg, err := strconv.Atoi(string(file[start:i])) // i-1??
+ if err != nil {
+ panic(err)
+ }
+ memory = append(memory, arg)
+ start = i + 1
+ size++
+ }
+ }
+ // fmt.Println(execute(memory, size))
+ // noun, verb := etucexe(memory, size, 19690720)
+ // fmt.Println(100*noun + verb)
+ execute(memory, size)
+}
+
+func split(memory []int, i, size, relative int) (int, int, int) {
+ mode := memory[i] / 100
+ three, two, one := i+3, i+2, i+1
+ if size-i > 1 {
+ if mode%10 == 0 {
+ one = memory[i+1]
+ } else if mode%10 == 2 {
+ one = relative + memory[i+1]
+ }
+ if size-i > 2 {
+ if mode/10%10 == 0 {
+ two = memory[i+2]
+ } else if mode%10 == 2 {
+ two = relative + memory[i+2]
+ }
+ if size-i > 3 {
+ if mode/100 == 0 {
+ three = memory[i+3]
+ } else if mode%10 == 2 {
+ three = relative + memory[i+3]
+ }
+ }
+ }
+ }
+ return three, two, one
+}
+
+func execute(memory []int, size int) []int {
+ /* todo: said "memory" functionality could be [pos, value]int
+ * i.e. when memory outside initial bounds wants to be accessed,
+ * it writes to a new element of this slice
+ * to access elements of the array, iterate through while checking each position
+ * additionally, to ensure there aren't conflicting "positions" in the array,
+ * do the above iteration process, if not, appends (this requires a total int)
+ */
+ /*
+ var swap [][2]int
+ */
+
+ // off-topic todo: https://www.golangprograms.com/example-arrays-of-arrays-arrays-of-slices-slices-of-arrays-and-slices-of-slices.html
+ // does this mean i can remove total / size because if so YES
+ for i := 0; i < 4000; i++ { // bad (example: no auto-termination due to 0 replacing nothingness)
+ memory = append(memory, 0)
+ }
+ relative := 0 // initial value of the relative base
+ for i := 0; i < len(memory); {
+ // bounds check
+ opcode := memory[i] % 100
+ three, two, one := split(memory, i, size, relative)
+ //fmt.Println("test:", opcode)
+ // actually what might work better than replacing all below would be
+ // checking if the next three values are out of bounds or not
+ // and then replacing them
+ // no bad idea large addition exists
+ switch opcode {
+ case 1: // adds
+ memory[three] = memory[one] + memory[two]
+ i += 4
+ case 2: // multiplies
+ // if out of bounds
+ // swap = append(swap, {memory[three], memory[one] * memory[two]})
+ // else
+ memory[three] = memory[one] * memory[two]
+ i += 4
+ case 3: // input
+ var input int
+ fmt.Print("Input: ")
+ resp, err := fmt.Scanf("%d", &input) // interesting note: anything following a valid integer is run by bash
+ if err != nil {
+ fmt.Println(resp, err)
+ os.Exit(0)
+ }
+ // out of bounds check
+ memory[one] = input // not affected by modes
+ i += 2
+ case 4: // output
+ fmt.Println(memory[one])
+ i += 2
+ case 5: // jump-if-true
+ if memory[one] != 0 {
+ i = memory[two]
+ } else {
+ i += 3
+ }
+ case 6: // jump-if-false
+ if memory[one] == 0 {
+ i = memory[two]
+ } else {
+ i += 3
+ }
+ case 7: // less than
+ if memory[one] < memory[two] {
+ memory[memory[i+3]] = 1 // instructions: _position_ given by the third parameter
+ } else {
+ memory[memory[i+3]] = 0
+ }
+ i += 4
+ case 8: // equals
+ if memory[one] == memory[two] {
+ memory[memory[i+3]] = 1
+ } else {
+ memory[memory[i+3]] = 0
+ }
+ i += 4
+ case 9: // adjusts the relative base
+ relative += memory[one] // interesting behavior when changing to i+1
+ i += 2
+ case 99: // terminate
+ return memory
+ default:
+ fmt.Println("Unsupported code", opcode, "at", i)
+ os.Exit(0)
+ }
+ }
+ return memory
+}
+
+func etucexe(memory []int, size, output int) (int, int) {
+ var volatile []int
+ for i := 0; i < len(memory); i++ {
+ for j := 0; j < len(memory); j++ {
+ volatile = append([]int(nil), memory...) // reset volatile to memory
+ volatile[1], volatile[2] = i, j
+ if execute(volatile, size)[0] == output {
+ return i, j
+ }
+ }
+ }
+ return -1, -1
+}