~zacbrown/aoc-2019-go

fef5e6cf245abbee79dda6f8f0f4ba616c48e5fa — Zac Brown 3 years ago e5639f8 master
Refactor out the Int Code Computer.

Signed-off-by: Zac Brown <git@zacbrown.org>
6 files changed, 332 insertions(+), 545 deletions(-)

M .gitignore
M cmd/day2/main.go
M cmd/day5/main.go
M cmd/day7/main.go
M cmd/day8/main.go
A computer.go
M .gitignore => .gitignore +3 -1
@@ 3,4 3,6 @@
# Unignore all with extensions
!*.*
# Unignore all dirs
!*/
\ No newline at end of file
!*/

.idea/
\ No newline at end of file

M cmd/day2/main.go => cmd/day2/main.go +11 -31
@@ 1,6 1,9 @@
package main

import "fmt"
import (
	"fmt"
	computer "git.sr.ht/~zacbrown/aoc-2019-go"
)

var intCodeProgram = []int{
	1, 0, 0, 3, 1, 1, 2, 3, 1, 3, 4, 3, 1, 5, 0, 3, 2, 13, 1, 19,


@@ 12,52 15,29 @@ var intCodeProgram = []int{
	107, 6, 111, 1, 111, 2, 115, 1, 115, 13, 0, 99, 2, 0, 14, 0,
}

func eval(program []int) []int {
	pc := program[:]
	for {
		// Perform whatever operation we're going to.
		switch pc[0] {
		case 1:
			inPos1 := pc[1]
			inPos2 := pc[2]
			outPos := pc[3]
			program[outPos] = program[inPos1] + program[inPos2]
			pc = pc[4:]
		case 2:
			inPos1 := pc[1]
			inPos2 := pc[2]
			outPos := pc[3]
			program[outPos] = program[inPos1] * program[inPos2]
			pc = pc[4:]
		case 99:
			return program
		}
	}
}

func main() {
	fmt.Println("============= PART 1 =============")
	programCopy := make([]int, len(intCodeProgram))
	copy(programCopy, intCodeProgram)
	programCopy[1] = 12
	programCopy[2] = 2
	result := eval(programCopy)
	fmt.Println("Program result: ", result[0])
	c := computer.NewComputer(programCopy)
	c.Eval(nil)
	fmt.Println("Program result: ", programCopy[0])

	// Part 2
	const targetValue int = 19690720
	fmt.Println("\n============= PART 2 =============")
	const targetValue int = 19690720
out:
	for ii := 0; ii < 99; ii++ {
		for jj := 0; jj < 99; jj++ {
			fmt.Printf("Trying noun=%d, verb=%d.\n", ii, jj)

			copy(programCopy, intCodeProgram)
			programCopy[1] = ii
			programCopy[2] = jj
			output := eval(programCopy)
			c := computer.NewComputer(programCopy)
			c.Eval(nil)

			if output[0] == targetValue {
			if programCopy[0] == targetValue {
				fmt.Printf("Match found: noun=%d, verb=%d.\n", ii, jj)
				fmt.Printf("Solution: 100 * %d + %d = %d\n", ii, jj, (100*ii)+jj)
				break out

M cmd/day5/main.go => cmd/day5/main.go +19 -216
@@ 1,11 1,8 @@
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
	computer "git.sr.ht/~zacbrown/aoc-2019-go"
)

var intCodeProgram = []int{


@@ 46,222 43,28 @@ var intCodeProgram = []int{
	1001, 223, 1, 223, 4, 223, 99, 226,
}

var reader *bufio.Reader

const (
	positionMode  = 0
	immediateMode = 1
)

func eval(program []int) []int {
	pc := program[:]
func main() {
	fmt.Println("============= PART 1 =============")
	programCopy := make([]int, len(intCodeProgram))
	copy(programCopy, intCodeProgram)
	c := computer.NewComputer(programCopy)
	input := []int{1}
	for {
		// If the instruction is 1002, we want the least two digits - the tens
		// and the ones position. To get this, we modulo by 100: 1002 % 100 = 02
		instr := pc[0] % 100
		// Perform whatever operation we're going to.
		switch instr {
		case 1:
			// Add
			in1 := pc[1]
			in1Mode := (pc[0] / 100) % 10
			in2 := pc[2]
			in2Mode := (pc[0] / 1000) % 10
			out := pc[3]

			var in1Value int
			if in1Mode == positionMode {
				in1Value = program[in1]
			} else {
				in1Value = in1
			}

			var in2Value int
			if in2Mode == positionMode {
				in2Value = program[in2]
			} else {
				in2Value = in2
			}

			program[out] = in1Value + in2Value
			pc = pc[4:]
		case 2:
			// Multiply
			in1 := pc[1]
			in1Mode := (pc[0] / 100) % 10
			in2 := pc[2]
			in2Mode := (pc[0] / 1000) % 10
			out := pc[3]

			var in1Value int
			if in1Mode == positionMode {
				in1Value = program[in1]
			} else {
				in1Value = in1
			}

			var in2Value int
			if in2Mode == positionMode {
				in2Value = program[in2]
			} else {
				in2Value = in2
			}

			program[out] = in1Value * in2Value
			pc = pc[4:]
		case 3:
			// Input
			print("input requested: ")
			inPos := pc[1]
			input, _ := reader.ReadString('\n')
			input = strings.Trim(input, " \n\t")

			inputAsInt, err := strconv.Atoi(input)
			if err != nil {
				panic(fmt.Sprintf("Non-integer input provided: %s. Err: %v", input, err))
			}

			program[inPos] = inputAsInt
			pc = pc[2:]
		case 4:
			// Output
			outPos := pc[1]
			outMode := (pc[0] / 100) % 10

			if outMode == positionMode {
				println(program[outPos])
			} else {
				println(outPos)
			}
			pc = pc[2:]
		case 5:
			// jump-if-true
			in1 := pc[1]
			in1Mode := (pc[0] / 100) % 10

			in2 := pc[2]
			in2Mode := (pc[0] / 1000) % 10

			var numToEval int
			if in1Mode == positionMode {
				numToEval = program[in1]
			} else {
				numToEval = in1
			}

			var targetPosition int
			if in2Mode == positionMode {
				targetPosition = program[in2]
			} else {
				targetPosition = in2
			}

			// Jump if it's non-zero.
			if numToEval != 0 {
				pc = program[targetPosition:]
			} else {
				pc = pc[3:]
			}
		case 6:
			// jump-if-false
			in1 := pc[1]
			in1Mode := (pc[0] / 100) % 10

			in2 := pc[2]
			in2Mode := (pc[0] / 1000) % 10

			var numToEval int
			if in1Mode == positionMode {
				numToEval = program[in1]
			} else {
				numToEval = in1
			}

			var targetPosition int
			if in2Mode == positionMode {
				targetPosition = program[in2]
			} else {
				targetPosition = in2
			}

			// Jump if it's zero.
			if numToEval == 0 {
				pc = program[targetPosition:]
			} else {
				pc = pc[3:]
			}
		case 7:
			// less than
			in1 := pc[1]
			in1Mode := (pc[0] / 100) % 10

			in2 := pc[2]
			in2Mode := (pc[0] / 1000) % 10

			outPos := pc[3]

			var left int
			if in1Mode == positionMode {
				left = program[in1]
			} else {
				left = in1
			}

			var right int
			if in2Mode == positionMode {
				right = program[in2]
			} else {
				right = in2
			}

			if left < right {
				program[outPos] = 1
			} else {
				program[outPos] = 0
			}
			pc = pc[4:]
		case 8:
			// less than
			in1 := pc[1]
			in1Mode := (pc[0] / 100) % 10

			in2 := pc[2]
			in2Mode := (pc[0] / 1000) % 10

			outPos := pc[3]

			var left int
			if in1Mode == positionMode {
				left = program[in1]
			} else {
				left = in1
			}

			var right int
			if in2Mode == positionMode {
				right = program[in2]
			} else {
				right = in2
			}

			if left == right {
				program[outPos] = 1
			} else {
				program[outPos] = 0
			}
			pc = pc[4:]
		case 99:
			return program
		// Output returns 'PAUSE' so we need to call it till we encounter
		// the `HALT` instruction.
		if c.Eval(input) == computer.HALT {
			break
		}
		// We only need a valid input on the first execution.
		input = nil
	}
}

func main() {
	print("Initialising STDIN reader... ")
	reader = bufio.NewReader(os.Stdin)
	println("FINISHED")
	fmt.Printf("Answer: %d\n", c.Output)

	programCopy := make([]int, len(intCodeProgram))
	fmt.Println("============= PART 2 =============")
	programCopy = make([]int, len(intCodeProgram))
	copy(programCopy, intCodeProgram)
	eval(programCopy)
	c = computer.NewComputer(programCopy)
	c.Eval([]int{5})
	fmt.Printf("Answer: %d\n", c.Output)
}

M cmd/day7/main.go => cmd/day7/main.go +50 -296
@@ 1,10 1,8 @@
package main

import (
	"bufio"
	"fmt"
	"strconv"
	"strings"
	computer "git.sr.ht/~zacbrown/aoc-2019-go"
)

var intCodeProgram = []int{


@@ 31,240 29,6 @@ var intCodeProgram = []int{
	3, 9, 101, 2, 9, 9, 4, 9, 99,
}

var reader *bufio.Reader

const (
	positionMode  = 0
	immediateMode = 1
)

type Program struct {
	inputs  []string
	program []int
	output  int
	pc      []int
}

func newProgram(program []int, inputs []string) *Program {
	return &Program{inputs, program, 0, program[:]}
}

const (
	PAUSE = iota
	HALT
)

func (p *Program) eval() int {
	for {
		// If the instruction is 1002, we want the least two digits - the tens
		// and the ones position. To get this, we modulo by 100: 1002 % 100 = 02
		instr := p.pc[0] % 100
		// Perform whatever operation we're going to.
		switch instr {
		case 1:
			// Add
			in1 := p.pc[1]
			in1Mode := (p.pc[0] / 100) % 10
			in2 := p.pc[2]
			in2Mode := (p.pc[0] / 1000) % 10
			out := p.pc[3]

			var in1Value int
			if in1Mode == positionMode {
				in1Value = p.program[in1]
			} else {
				in1Value = in1
			}

			var in2Value int
			if in2Mode == positionMode {
				in2Value = p.program[in2]
			} else {
				in2Value = in2
			}

			p.program[out] = in1Value + in2Value
			p.pc = p.pc[4:]
		case 2:
			// Multiply
			in1 := p.pc[1]
			in1Mode := (p.pc[0] / 100) % 10
			in2 := p.pc[2]
			in2Mode := (p.pc[0] / 1000) % 10
			out := p.pc[3]

			var in1Value int
			if in1Mode == positionMode {
				in1Value = p.program[in1]
			} else {
				in1Value = in1
			}

			var in2Value int
			if in2Mode == positionMode {
				in2Value = p.program[in2]
			} else {
				in2Value = in2
			}

			p.program[out] = in1Value * in2Value
			p.pc = p.pc[4:]
		case 3:
			// Input
			print("input requested: ")
			inPos := p.pc[1]
			input := p.inputs[0] // Use a sentinel instead
			println(input)
			p.inputs = p.inputs[1:] // pop the head off
			input = strings.Trim(input, " \n\t")

			inputAsInt, err := strconv.Atoi(input)
			if err != nil {
				panic(fmt.Sprintf("Non-integer input provided: %s. Err: %v", input, err))
			}

			p.program[inPos] = inputAsInt
			p.pc = p.pc[2:]
		case 4:
			// Output
			outPos := p.pc[1]
			outMode := (p.pc[0] / 100) % 10

			if outMode == positionMode {
				println(p.program[outPos])
				p.output = p.program[outPos]
			} else {
				println(outPos)
				p.output = outPos
			}

			outputVal := strconv.Itoa(p.output)
			p.inputs = append(p.inputs, outputVal)

			p.pc = p.pc[2:]
			return PAUSE
		case 5:
			// jump-if-true
			in1 := p.pc[1]
			in1Mode := (p.pc[0] / 100) % 10

			in2 := p.pc[2]
			in2Mode := (p.pc[0] / 1000) % 10

			var numToEval int
			if in1Mode == positionMode {
				numToEval = p.program[in1]
			} else {
				numToEval = in1
			}

			var targetPosition int
			if in2Mode == positionMode {
				targetPosition = p.program[in2]
			} else {
				targetPosition = in2
			}

			// Jump if it's non-zero.
			if numToEval != 0 {
				p.pc = p.program[targetPosition:]
			} else {
				p.pc = p.pc[3:]
			}
		case 6:
			// jump-if-false
			in1 := p.pc[1]
			in1Mode := (p.pc[0] / 100) % 10

			in2 := p.pc[2]
			in2Mode := (p.pc[0] / 1000) % 10

			var numToEval int
			if in1Mode == positionMode {
				numToEval = p.program[in1]
			} else {
				numToEval = in1
			}

			var targetPosition int
			if in2Mode == positionMode {
				targetPosition = p.program[in2]
			} else {
				targetPosition = in2
			}

			// Jump if it's zero.
			if numToEval == 0 {
				p.pc = p.program[targetPosition:]
			} else {
				p.pc = p.pc[3:]
			}
		case 7:
			// less than
			in1 := p.pc[1]
			in1Mode := (p.pc[0] / 100) % 10

			in2 := p.pc[2]
			in2Mode := (p.pc[0] / 1000) % 10

			outPos := p.pc[3]

			var left int
			if in1Mode == positionMode {
				left = p.program[in1]
			} else {
				left = in1
			}

			var right int
			if in2Mode == positionMode {
				right = p.program[in2]
			} else {
				right = in2
			}

			if left < right {
				p.program[outPos] = 1
			} else {
				p.program[outPos] = 0
			}
			p.pc = p.pc[4:]
		case 8:
			// less than
			in1 := p.pc[1]
			in1Mode := (p.pc[0] / 100) % 10

			in2 := p.pc[2]
			in2Mode := (p.pc[0] / 1000) % 10

			outPos := p.pc[3]

			var left int
			if in1Mode == positionMode {
				left = p.program[in1]
			} else {
				left = in1
			}

			var right int
			if in2Mode == positionMode {
				right = p.program[in2]
			} else {
				right = in2
			}

			if left == right {
				p.program[outPos] = 1
			} else {
				p.program[outPos] = 0
			}
			p.pc = p.pc[4:]
		case 99:
			return HALT
		}
	}
}

var phaseSettingValuePart1 = []int{0, 1, 2, 3, 4}
var phaseSettingValuePart2 = []int{5, 6, 7, 8, 9}
var phaseSettingPermutations [][]int


@@ 296,57 60,55 @@ func part1() int {
		// A
		programCopyA := make([]int, len(intCodeProgram))
		copy(programCopyA, intCodeProgram)
		phaseSetting := strconv.Itoa(permutation[0])
		println("phase setting A: ", permutation[0])
		inputSignal := "0"
		pA := newProgram(programCopyA, []string{
			phaseSetting,
			inputSignal,
		pA := computer.NewComputer(programCopyA)
		pA.Eval([]int{
			permutation[0],
			0,
		})
		pA.eval()

		// B
		programCopyB := make([]int, len(intCodeProgram))
		copy(programCopyB, intCodeProgram)
		println("phase setting B: ", permutation[1])
		pB := newProgram(programCopyB, []string{
			strconv.Itoa(permutation[1]),
			strconv.Itoa(pA.output),
		pB := computer.NewComputer(programCopyB)
		pB.Eval([]int{
			permutation[1],
			pA.Output,
		})
		pB.eval()

		// C
		programCopyC := make([]int, len(intCodeProgram))
		copy(programCopyC, intCodeProgram)
		println("phase setting C: ", permutation[2])
		pC := newProgram(programCopyC, []string{
			strconv.Itoa(permutation[2]),
			strconv.Itoa(pB.output),
		pC := computer.NewComputer(programCopyC)
		pC.Eval([]int{
			permutation[2],
			pB.Output,
		})
		pC.eval()

		// D
		programCopyD := make([]int, len(intCodeProgram))
		copy(programCopyD, intCodeProgram)
		println("phase setting D: ", permutation[3])
		pD := newProgram(programCopyD, []string{
			strconv.Itoa(permutation[3]),
			strconv.Itoa(pC.output),
		pD := computer.NewComputer(programCopyD)
		pD.Eval([]int{
			permutation[3],
			pC.Output,
		})
		pD.eval()

		// E
		programCopyE := make([]int, len(intCodeProgram))
		copy(programCopyE, intCodeProgram)
		println("phase setting E: ", permutation[4])
		pE := newProgram(programCopyE, []string{
			strconv.Itoa(permutation[4]),
			strconv.Itoa(pD.output),
		pE := computer.NewComputer(programCopyE)
		pE.Eval([]int{
			permutation[4],
			pD.Output,
		})
		pE.eval()

		if pE.output > highSignal {
			highSignal = pE.output
		if pE.Output > highSignal {
			highSignal = pE.Output
		}
	}
	return highSignal


@@ 362,87 124,79 @@ func part2() int {
		// A
		programCopyA := make([]int, len(intCodeProgram))
		copy(programCopyA, intCodeProgram)
		phaseSetting := strconv.Itoa(permutation[0])
		inputSignal := "0"
		pA := newProgram(programCopyA, []string{
			phaseSetting,
		inputSignal := 0
		pA := computer.NewComputer(programCopyA)
		pA.Eval( []int{
			permutation[0],
			inputSignal,
		})
		pA.eval()

		// B
		programCopyB := make([]int, len(intCodeProgram))
		copy(programCopyB, intCodeProgram)
		pB := newProgram(programCopyB, []string{
			strconv.Itoa(permutation[1]),
			strconv.Itoa(pA.output),
		pB := computer.NewComputer(programCopyB)
		pB.Eval([]int{
			permutation[1],
			pA.Output,
		})
		pB.eval()

		// C
		programCopyC := make([]int, len(intCodeProgram))
		copy(programCopyC, intCodeProgram)
		pC := newProgram(programCopyC, []string{
			strconv.Itoa(permutation[2]),
			strconv.Itoa(pB.output),
		pC := computer.NewComputer(programCopyC)
		pC.Eval([]int{
			permutation[2],
			pB.Output,
		})
		pC.eval()

		// D
		programCopyD := make([]int, len(intCodeProgram))
		copy(programCopyD, intCodeProgram)
		pD := newProgram(programCopyD, []string{
			strconv.Itoa(permutation[3]),
			strconv.Itoa(pC.output),
		pD := computer.NewComputer(programCopyD)
		pD.Eval([]int{
			permutation[3],
			pC.Output,
		})
		pD.eval()

		// E
		programCopyE := make([]int, len(intCodeProgram))
		copy(programCopyE, intCodeProgram)
		pE := newProgram(programCopyE, []string{
			strconv.Itoa(permutation[4]),
			strconv.Itoa(pD.output),
		pE := computer.NewComputer(programCopyE)
		pE.Eval([]int{
			permutation[4],
			pD.Output,
		})
		pE.eval()

		for {
			// Phase settings are set. Now grab the output from first run of E.
			pA.inputs = []string{strconv.Itoa(pE.output)}

			// Now run them in feedback mode.
			println("Run part A")
			if pA.eval() == HALT {
			if pA.Eval([]int{pE.Output}) == computer.HALT {
				break
			}

			pB.inputs = []string{strconv.Itoa(pA.output)}
			println("Run part B")
			if pB.eval() == HALT {
			if pB.Eval([]int{pA.Output}) == computer.HALT {
				panic("we halted at B?")
			}

			pC.inputs = []string{strconv.Itoa(pB.output)}
			println("Run part C")
			if pC.eval() == HALT {
			if pC.Eval([]int{pB.Output}) == computer.HALT {
				panic("we halted at C?")
			}

			pD.inputs = []string{strconv.Itoa(pC.output)}
			println("Run part D")
			if pD.eval() == HALT {
			if pD.Eval([]int{pC.Output}) == computer.HALT {
				panic("we halted at D?")
			}

			pE.inputs = []string{strconv.Itoa(pD.output)}
			println("Run part E")
			if pE.eval() == HALT {
			if pE.Eval([]int{pD.Output}) == computer.HALT {
				panic("we halted at E?")
			}
		}

		if pE.output > highSignal {
			highSignal = pE.output
		if pE.Output > highSignal {
			highSignal = pE.Output
		}
	}
	return highSignal

M cmd/day8/main.go => cmd/day8/main.go +1 -1
@@ 39,7 39,7 @@ const (
type Layer [imageHeight][imageWidth]int

func buildImageLayers(imageData string) []Layer {
	layers := []Layer{}
	var layers []Layer

	imageDataIdx := 0
	for imageDataIdx < len(imageData) {

A computer.go => computer.go +248 -0
@@ 0,0 1,248 @@
package computer

const (
	PositionMode  = 0
	ImmediateMode = 1
)

type Computer struct {
	inputs  []int
	program []int
	Output  int
	pc      []int
}

func NewComputer(program []int) *Computer {
	return &Computer{nil, program, 0, program[:]}
}

const (
	PAUSE = iota
	HALT
)

func (c *Computer) instrAdd() {
	// Add
	in1 := c.pc[1]
	in1Mode := (c.pc[0] / 100) % 10
	in2 := c.pc[2]
	in2Mode := (c.pc[0] / 1000) % 10
	out := c.pc[3]

	var in1Value int
	if in1Mode == PositionMode {
		in1Value = c.program[in1]
	} else {
		in1Value = in1
	}

	var in2Value int
	if in2Mode == PositionMode {
		in2Value = c.program[in2]
	} else {
		in2Value = in2
	}

	c.program[out] = in1Value + in2Value
	c.pc = c.pc[4:]
}

func (c *Computer) instrMultiply() {
	in1 := c.pc[1]
	in1Mode := (c.pc[0] / 100) % 10
	in2 := c.pc[2]
	in2Mode := (c.pc[0] / 1000) % 10
	out := c.pc[3]

	var in1Value int
	if in1Mode == PositionMode {
		in1Value = c.program[in1]
	} else {
		in1Value = in1
	}

	var in2Value int
	if in2Mode == PositionMode {
		in2Value = c.program[in2]
	} else {
		in2Value = in2
	}

	c.program[out] = in1Value * in2Value
	c.pc = c.pc[4:]
}

func (c *Computer) instrInput() {
	inPos := c.pc[1]

	c.program[inPos] =  c.inputs[0]
	c.inputs = c.inputs[1:] // pop the head off

	c.pc = c.pc[2:]
}

func (c *Computer) instrOutput() {
	outPos := c.pc[1]
	outMode := (c.pc[0] / 100) % 10

	if outMode == PositionMode {
		c.Output = c.program[outPos]
	} else {
		c.Output = outPos
	}

	println("[DIAG] Output instruction: ", c.Output)

	c.pc = c.pc[2:]
}

func (c *Computer) instrJumpIfTrue() {
	in1 := c.pc[1]
	in1Mode := (c.pc[0] / 100) % 10

	in2 := c.pc[2]
	in2Mode := (c.pc[0] / 1000) % 10

	var numToEval int
	if in1Mode == PositionMode {
		numToEval = c.program[in1]
	} else {
		numToEval = in1
	}

	var targetPosition int
	if in2Mode == PositionMode {
		targetPosition = c.program[in2]
	} else {
		targetPosition = in2
	}

	// Jump if it's non-zero.
	if numToEval != 0 {
		c.pc = c.program[targetPosition:]
	} else {
		c.pc = c.pc[3:]
	}
}

func (c *Computer) instrJumpIfFalse() {
	in1 := c.pc[1]
	in1Mode := (c.pc[0] / 100) % 10

	in2 := c.pc[2]
	in2Mode := (c.pc[0] / 1000) % 10

	var numToEval int
	if in1Mode == PositionMode {
		numToEval = c.program[in1]
	} else {
		numToEval = in1
	}

	var targetPosition int
	if in2Mode == PositionMode {
		targetPosition = c.program[in2]
	} else {
		targetPosition = in2
	}

	// Jump if it's zero.
	if numToEval == 0 {
		c.pc = c.program[targetPosition:]
	} else {
		c.pc = c.pc[3:]
	}
}

func (c *Computer) instrLessThan() {
	in1 := c.pc[1]
	in1Mode := (c.pc[0] / 100) % 10

	in2 := c.pc[2]
	in2Mode := (c.pc[0] / 1000) % 10

	outPos := c.pc[3]

	var left int
	if in1Mode == PositionMode {
		left = c.program[in1]
	} else {
		left = in1
	}

	var right int
	if in2Mode == PositionMode {
		right = c.program[in2]
	} else {
		right = in2
	}

	if left < right {
		c.program[outPos] = 1
	} else {
		c.program[outPos] = 0
	}
	c.pc = c.pc[4:]
}

func (c *Computer) instrEqual() {
	in1 := c.pc[1]
	in1Mode := (c.pc[0] / 100) % 10

	in2 := c.pc[2]
	in2Mode := (c.pc[0] / 1000) % 10

	outPos := c.pc[3]

	var left int
	if in1Mode == PositionMode {
		left = c.program[in1]
	} else {
		left = in1
	}

	var right int
	if in2Mode == PositionMode {
		right = c.program[in2]
	} else {
		right = in2
	}

	if left == right {
		c.program[outPos] = 1
	} else {
		c.program[outPos] = 0
	}
	c.pc = c.pc[4:]
}

func (c *Computer) Eval(inputs []int) int {
	c.inputs = inputs
	for {
		// If the instruction is 1002, we want the least two digits - the tens
		// and the ones position. To get this, we modulo by 100: 1002 % 100 = 02
		instr := c.pc[0] % 100
		// Perform whatever operation we're going to.
		switch instr {
		case 1:
			c.instrAdd()
		case 2:
			c.instrMultiply()
		case 3:
			c.instrInput()
		case 4:
			c.instrOutput()
			return PAUSE
		case 5:
			c.instrJumpIfTrue()
		case 6:
			c.instrJumpIfFalse()
		case 7:
			c.instrLessThan()
		case 8:
			c.instrEqual()
		case 99:
			return HALT
		}
	}
}
\ No newline at end of file