2019-12-05 15:53:40 +00:00
|
|
|
package aoc2019
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
)
|
2019-12-05 15:53:40 +00:00
|
|
|
|
|
|
|
func TestParseOpCode(t *testing.T) {
|
2019-12-09 17:48:40 +00:00
|
|
|
for code, expOpCode := range map[int64]opCode{
|
2019-12-05 15:53:40 +00:00
|
|
|
1002: {Type: opCodeTypeMultiplication, flags: []opCodeFlag{opCodeFlagPosition, opCodeFlagImmediate}},
|
|
|
|
1101: {Type: opCodeTypeAddition, flags: []opCodeFlag{opCodeFlagImmediate, opCodeFlagImmediate}},
|
|
|
|
} {
|
|
|
|
if op := parseOpCode(code); !op.eq(expOpCode) {
|
|
|
|
t.Errorf("OpCode execution of code %d yield unexpected result: exp=%+v got=%+v", code, expOpCode, op)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExecuteIntcodeIO(t *testing.T) {
|
|
|
|
code, _ := parseIntcode("3,0,4,0,99")
|
|
|
|
|
|
|
|
var (
|
2019-12-09 17:48:40 +00:00
|
|
|
exp int64 = 25
|
|
|
|
in = make(chan int64, 1)
|
|
|
|
out = make(chan int64, 1)
|
2019-12-05 15:53:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
in <- exp
|
|
|
|
|
|
|
|
if _, err := executeIntcode(code, in, out); err != nil {
|
|
|
|
t.Fatalf("Intcode execution failed: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r := <-out; r != exp {
|
|
|
|
t.Errorf("Program yield unexpected result: exp=%d got=%d", exp, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExecuteIntcodeImmediateFlag(t *testing.T) {
|
|
|
|
// 102,4,7,0 = Multiply 4 by pos_7, store to pos_0
|
|
|
|
// 4,0 = Output pos_0
|
|
|
|
// 99 = Exit
|
|
|
|
// 3 = pos_7
|
|
|
|
code, _ := parseIntcode("102,4,7,0,4,0,99,3")
|
|
|
|
|
|
|
|
var (
|
2019-12-09 17:48:40 +00:00
|
|
|
exp int64 = 12
|
|
|
|
out = make(chan int64, 1)
|
2019-12-05 15:53:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if _, err := executeIntcode(code, nil, out); err != nil {
|
|
|
|
t.Fatalf("Intcode execution failed: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r := <-out; r != exp {
|
|
|
|
t.Errorf("Program yield unexpected result: exp=%d got=%d", exp, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExecuteIntcodeEquals(t *testing.T) {
|
|
|
|
for mode, codeStr := range map[string]string{
|
|
|
|
"position": "3,9,8,9,10,9,4,9,99,-1,8",
|
|
|
|
"immediate": "3,3,1108,-1,8,3,4,3,99",
|
|
|
|
} {
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
for input, exp := range map[int64]int64{
|
2019-12-05 15:53:40 +00:00
|
|
|
1: 0,
|
|
|
|
8: 1,
|
|
|
|
20: 0,
|
|
|
|
-8: 0,
|
|
|
|
} {
|
|
|
|
var (
|
2019-12-09 17:48:40 +00:00
|
|
|
in = make(chan int64, 1)
|
|
|
|
out = make(chan int64, 10)
|
2019-12-05 15:53:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
code, _ := parseIntcode(codeStr)
|
|
|
|
in <- input
|
|
|
|
|
|
|
|
if _, err := executeIntcode(code, in, out); err != nil {
|
|
|
|
t.Fatalf("Execute in mode %q with input %d caused an error: %s", mode, input, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r := <-out; r != exp {
|
|
|
|
t.Errorf("Execute in mode %q with input %d yield unexpected result: exp=%d got=%d", mode, input, exp, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExecuteIntcodeLessThan(t *testing.T) {
|
|
|
|
for mode, codeStr := range map[string]string{
|
|
|
|
"position": "3,9,7,9,10,9,4,9,99,-1,8",
|
|
|
|
"immediate": "3,3,1107,-1,8,3,4,3,99",
|
|
|
|
} {
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
for input, exp := range map[int64]int64{
|
2019-12-05 15:53:40 +00:00
|
|
|
1: 1,
|
|
|
|
8: 0,
|
|
|
|
20: 0,
|
|
|
|
-8: 1,
|
|
|
|
} {
|
|
|
|
var (
|
2019-12-09 17:48:40 +00:00
|
|
|
in = make(chan int64, 1)
|
|
|
|
out = make(chan int64, 10)
|
2019-12-05 15:53:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
code, _ := parseIntcode(codeStr)
|
|
|
|
in <- input
|
|
|
|
|
|
|
|
if _, err := executeIntcode(code, in, out); err != nil {
|
|
|
|
t.Fatalf("Execute in mode %q with input %d caused an error: %s", mode, input, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r := <-out; r != exp {
|
|
|
|
t.Errorf("Execute in mode %q with input %d yield unexpected result: exp=%d got=%d", mode, input, exp, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExecuteIntcodeJump(t *testing.T) {
|
|
|
|
for mode, codeStr := range map[string]string{
|
|
|
|
"position": "3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9",
|
|
|
|
"immediate": "3,3,1105,-1,9,1101,0,0,12,4,12,99,1",
|
|
|
|
} {
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
for input, exp := range map[int64]int64{
|
2019-12-05 15:53:40 +00:00
|
|
|
5: 1,
|
|
|
|
0: 0,
|
|
|
|
} {
|
|
|
|
var (
|
2019-12-09 17:48:40 +00:00
|
|
|
in = make(chan int64, 1)
|
|
|
|
out = make(chan int64, 10)
|
2019-12-05 15:53:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
code, _ := parseIntcode(codeStr)
|
|
|
|
in <- input
|
|
|
|
|
|
|
|
if _, err := executeIntcode(code, in, out); err != nil {
|
|
|
|
t.Fatalf("Execute in mode %q with input %d caused an error: %s", mode, input, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r := <-out; r != exp {
|
|
|
|
t.Errorf("Execute in mode %q with input %d yield unexpected result: exp=%d got=%d", mode, input, exp, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2019-12-09 17:48:40 +00:00
|
|
|
|
|
|
|
func TestExecuteIntcodeRelativeBase(t *testing.T) {
|
|
|
|
code, _ := parseIntcode("109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99")
|
|
|
|
|
|
|
|
var (
|
|
|
|
codeCopy []int64
|
|
|
|
out = make(chan int64, 1)
|
|
|
|
)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
if _, err := executeIntcode(code, nil, out); err != nil {
|
|
|
|
t.Fatalf("Intcode execution failed: %s", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for v := range out {
|
|
|
|
codeCopy = append(codeCopy, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(codeCopy, code) {
|
|
|
|
t.Errorf("Program yield unexpected result: exp=%d got=%d", code, codeCopy)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExecuteIntcodeLargeNumber(t *testing.T) {
|
|
|
|
for codeStr, expValue := range map[string]int64{
|
|
|
|
"1102,34915192,34915192,7,4,7,99,0": 1219070632396864,
|
|
|
|
"104,1125899906842624,99": 1125899906842624,
|
|
|
|
} {
|
|
|
|
code, _ := parseIntcode(codeStr)
|
|
|
|
var out = make(chan int64, 1)
|
|
|
|
|
|
|
|
if _, err := executeIntcode(code, nil, out); err != nil {
|
|
|
|
t.Fatalf("Intcode execution failed: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r := <-out; r != expValue {
|
|
|
|
t.Errorf("Execute yield unexpected result: exp=%d got=%d", expValue, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|