diff --git a/day02.go b/day02.go index 5a249a1..a927104 100644 --- a/day02.go +++ b/day02.go @@ -7,13 +7,13 @@ import ( "github.com/pkg/errors" ) -func parseDay02Intcode(code string) ([]int, error) { return parseIntcode(code) } +func parseDay02Intcode(code string) ([]int64, error) { return parseIntcode(code) } -func executeDay02Intcode(code []int) ([]int, error) { +func executeDay02Intcode(code []int64) ([]int64, error) { return executeIntcode(code, nil, nil) // Day02 intcode may not contain I/O } -func solveDay2Part1(inFile string) (int, error) { +func solveDay2Part1(inFile string) (int64, error) { raw, err := ioutil.ReadFile(inFile) if err != nil { return 0, errors.Wrap(err, "Unable to read input") @@ -37,16 +37,16 @@ func solveDay2Part1(inFile string) (int, error) { return code[0], nil } -func solveDay2Part2(inFile string) (int, error) { +func solveDay2Part2(inFile string) (int64, error) { raw, err := ioutil.ReadFile(inFile) if err != nil { return 0, errors.Wrap(err, "Unable to read input") } - const expectedResult int = 19690720 + const expectedResult int64 = 19690720 - for noun := 0; noun < 100; noun++ { - for verb := 0; verb < 100; verb++ { + for noun := int64(0); noun < 100; noun++ { + for verb := int64(0); verb < 100; verb++ { // Re-initialize "memory" code, err := parseDay02Intcode(strings.TrimSpace(string(raw))) diff --git a/day02_test.go b/day02_test.go index 3735818..e090a40 100644 --- a/day02_test.go +++ b/day02_test.go @@ -6,7 +6,7 @@ import ( ) func TestExecuteDay02Intcode(t *testing.T) { - for codeStr, expResult := range map[string][]int{ + for codeStr, expResult := range map[string][]int64{ "1,0,0,0,99": {2, 0, 0, 0, 99}, "2,3,0,3,99": {2, 3, 0, 6, 99}, "2,4,4,5,99,0": {2, 4, 4, 5, 99, 9801}, diff --git a/day05.go b/day05.go index 38c23f5..b14aeb0 100644 --- a/day05.go +++ b/day05.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" ) -func solveDay5FromFile(inFile string, diagProgram int) (int, error) { +func solveDay5FromFile(inFile string, diagProgram int64) (int64, error) { raw, err := ioutil.ReadFile(inFile) if err != nil { return 0, errors.Wrap(err, "Unable to read input") @@ -19,9 +19,9 @@ func solveDay5FromFile(inFile string, diagProgram int) (int, error) { } var ( - in = make(chan int, 1) - out = make(chan int, len(code)) // There cannot be more outputs than number of code parts - outputs []int + in = make(chan int64, 1) + out = make(chan int64, len(code)) // There cannot be more outputs than number of code parts + outputs []int64 ) /* @@ -52,7 +52,7 @@ func solveDay5FromFile(inFile string, diagProgram int) (int, error) { return outputs[len(outputs)-1], nil } -func solveDay5Part1(inFile string) (int, error) { +func solveDay5Part1(inFile string) (int64, error) { /* * The TEST diagnostic program will start by requesting from the user * the ID of the system to test by running an input instruction - provide @@ -61,7 +61,7 @@ func solveDay5Part1(inFile string) (int, error) { return solveDay5FromFile(inFile, 1) } -func solveDay5Part2(inFile string) (int, error) { +func solveDay5Part2(inFile string) (int64, error) { /* * This time, when the TEST diagnostic program runs its input * instruction to get the ID of the system to test, provide it 5, diff --git a/day07.go b/day07.go index 8d3e149..9ffde08 100644 --- a/day07.go +++ b/day07.go @@ -7,17 +7,17 @@ import ( "github.com/pkg/errors" ) -func day07TestMaxOutputFromChain(code []int, chainStart, chainEnd int, looped bool) int { +func day07TestMaxOutputFromChain(code []int64, chainStart, chainEnd int, looped bool) int64 { var ( chainLen = chainEnd - chainStart + 1 - permuts [][]int - permute func(a []int, k int) - rootSeq = make([]int, chainLen) + permuts [][]int64 + permute func(a []int64, k int) + rootSeq = make([]int64, chainLen) ) - permute = func(a []int, k int) { + permute = func(a []int64, k int) { if k == len(a) { - permuts = append(permuts, append([]int{}, a...)) + permuts = append(permuts, append([]int64{}, a...)) } else { for i := k; i < len(rootSeq); i++ { a[k], a[i] = a[i], a[k] @@ -28,20 +28,20 @@ func day07TestMaxOutputFromChain(code []int, chainStart, chainEnd int, looped bo } for i := range rootSeq { - rootSeq[i] = chainStart + i + rootSeq[i] = int64(chainStart + i) } permute(rootSeq, 0) - var maxOutput int + var maxOutput int64 for _, seq := range permuts { var ( - commInChans = make([]chan int, chainLen) - commOut = make(chan int, 2) + commInChans = make([]chan int64, chainLen) + commOut = make(chan int64, 2) ) // Create channels for i := range commInChans { - commInChans[i] = make(chan int, 2) + commInChans[i] = make(chan int64, 2) } // Build execution chain @@ -56,7 +56,7 @@ func day07TestMaxOutputFromChain(code []int, chainStart, chainEnd int, looped bo } commInChans[0] <- 0 // Input signal - var lastOutput int + var lastOutput int64 for r := range commOut { lastOutput = r if looped { @@ -73,7 +73,7 @@ func day07TestMaxOutputFromChain(code []int, chainStart, chainEnd int, looped bo return maxOutput } -func solveDay7Part1(inFile string) (int, error) { +func solveDay7Part1(inFile string) (int64, error) { raw, err := ioutil.ReadFile(inFile) if err != nil { return 0, errors.Wrap(err, "Unable to read input file") @@ -87,7 +87,7 @@ func solveDay7Part1(inFile string) (int, error) { return day07TestMaxOutputFromChain(code, 0, 4, false), nil } -func solveDay7Part2(inFile string) (int, error) { +func solveDay7Part2(inFile string) (int64, error) { raw, err := ioutil.ReadFile(inFile) if err != nil { return 0, errors.Wrap(err, "Unable to read input file") diff --git a/day07_test.go b/day07_test.go index a11b84b..3730dc3 100644 --- a/day07_test.go +++ b/day07_test.go @@ -10,12 +10,12 @@ func TestChainedInput(t *testing.T) { // Create channels var ( - aIn = make(chan int, 2) - bIn = make(chan int, 2) - cIn = make(chan int, 2) - dIn = make(chan int, 2) - eIn = make(chan int, 2) - eOut = make(chan int, 2) + aIn = make(chan int64, 2) + bIn = make(chan int64, 2) + cIn = make(chan int64, 2) + dIn = make(chan int64, 2) + eIn = make(chan int64, 2) + eOut = make(chan int64, 2) ) // Build execution chain @@ -40,7 +40,7 @@ func TestChainedInput(t *testing.T) { } func TestMaxOutputFromChain(t *testing.T) { - for codeStr, expValue := range map[string]int{ + for codeStr, expValue := range map[string]int64{ "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0": 43210, "3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0": 54321, "3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0": 65210, @@ -57,7 +57,7 @@ func TestMaxOutputFromChain(t *testing.T) { } func TestMaxOutputFromLoopedChain(t *testing.T) { - for codeStr, expValue := range map[string]int{ + for codeStr, expValue := range map[string]int64{ "3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5": 139629729, "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": 18216, } { diff --git a/day09.go b/day09.go new file mode 100644 index 0000000..8ceefb3 --- /dev/null +++ b/day09.go @@ -0,0 +1,75 @@ +package aoc2019 + +import ( + "io/ioutil" + "strings" + "sync" + + "github.com/pkg/errors" +) + +func solveDay9Part1(inFile string) (int64, error) { + raw, err := ioutil.ReadFile(inFile) + if err != nil { + return 0, errors.Wrap(err, "Unable to read input file") + } + + code, err := parseIntcode(strings.TrimSpace(string(raw))) + if err != nil { + return 0, errors.Wrap(err, "Unable to parse intcode program") + } + + var ( + inChan = make(chan int64, 1) + outChan = make(chan int64, 1) + output []int64 + wg sync.WaitGroup + ) + + inChan <- 1 + wg.Add(1) + + go func() { + for v := range outChan { + output = append(output, v) + } + wg.Done() + }() + + if _, err := executeIntcode(code, inChan, outChan); err != nil { + return 0, errors.Wrap(err, "Unable to execute intcode") + } + + wg.Wait() + + if len(output) != 1 { + return 0, errors.Errorf("Got malfunction information: %+v", output) + } + + return output[0], nil +} + +func solveDay9Part2(inFile string) (int64, error) { + raw, err := ioutil.ReadFile(inFile) + if err != nil { + return 0, errors.Wrap(err, "Unable to read input file") + } + + code, err := parseIntcode(strings.TrimSpace(string(raw))) + if err != nil { + return 0, errors.Wrap(err, "Unable to parse intcode program") + } + + var ( + inChan = make(chan int64, 1) + outChan = make(chan int64, 1) + ) + + inChan <- 2 + + if _, err := executeIntcode(code, inChan, outChan); err != nil { + return 0, errors.Wrap(err, "Unable to execute intcode") + } + + return <-outChan, nil +} diff --git a/day09_input.txt b/day09_input.txt new file mode 100644 index 0000000..cc65a3c --- /dev/null +++ b/day09_input.txt @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,0,1020,1101,34,0,1004,1101,0,26,1008,1102,1,37,1011,1101,39,0,1018,1102,587,1,1022,1101,1,0,1021,1102,22,1,1012,1101,0,33,1014,1101,24,0,1016,1101,0,752,1029,1101,36,0,1002,1101,35,0,1006,1101,32,0,1009,1102,38,1,1003,1102,584,1,1023,1101,0,20,1001,1102,892,1,1025,1102,29,1,1000,1101,411,0,1026,1102,1,901,1024,1101,0,761,1028,1101,23,0,1017,1102,30,1,1013,1101,0,27,1015,1102,28,1,1005,1101,408,0,1027,1101,25,0,1007,1102,31,1,1019,1101,0,21,1010,109,5,1207,-2,39,63,1005,63,199,4,187,1105,1,203,1001,64,1,64,1002,64,2,64,109,12,21102,40,1,-1,1008,1016,40,63,1005,63,229,4,209,1001,64,1,64,1106,0,229,1002,64,2,64,109,-5,1207,-5,24,63,1005,63,249,1001,64,1,64,1106,0,251,4,235,1002,64,2,64,109,-14,2102,1,6,63,1008,63,32,63,1005,63,271,1106,0,277,4,257,1001,64,1,64,1002,64,2,64,109,2,1202,1,1,63,1008,63,20,63,1005,63,303,4,283,1001,64,1,64,1106,0,303,1002,64,2,64,109,7,2108,34,2,63,1005,63,319,1106,0,325,4,309,1001,64,1,64,1002,64,2,64,109,6,2101,0,-6,63,1008,63,24,63,1005,63,349,1001,64,1,64,1105,1,351,4,331,1002,64,2,64,109,4,21107,41,42,0,1005,1017,369,4,357,1105,1,373,1001,64,1,64,1002,64,2,64,109,5,21101,42,0,-5,1008,1017,41,63,1005,63,397,1001,64,1,64,1106,0,399,4,379,1002,64,2,64,109,9,2106,0,-4,1106,0,417,4,405,1001,64,1,64,1002,64,2,64,109,-20,21108,43,43,0,1005,1011,435,4,423,1105,1,439,1001,64,1,64,1002,64,2,64,109,-15,2102,1,8,63,1008,63,34,63,1005,63,465,4,445,1001,64,1,64,1105,1,465,1002,64,2,64,109,3,1201,6,0,63,1008,63,28,63,1005,63,491,4,471,1001,64,1,64,1106,0,491,1002,64,2,64,109,18,21108,44,46,0,1005,1017,511,1001,64,1,64,1106,0,513,4,497,1002,64,2,64,109,12,1205,-8,527,4,519,1105,1,531,1001,64,1,64,1002,64,2,64,109,-17,1208,-3,32,63,1005,63,553,4,537,1001,64,1,64,1105,1,553,1002,64,2,64,109,-13,1208,10,31,63,1005,63,573,1001,64,1,64,1105,1,575,4,559,1002,64,2,64,109,17,2105,1,7,1105,1,593,4,581,1001,64,1,64,1002,64,2,64,109,-8,2107,19,-7,63,1005,63,615,4,599,1001,64,1,64,1105,1,615,1002,64,2,64,109,4,1206,8,629,4,621,1106,0,633,1001,64,1,64,1002,64,2,64,109,-2,2101,0,-6,63,1008,63,34,63,1005,63,655,4,639,1105,1,659,1001,64,1,64,1002,64,2,64,109,10,1205,0,671,1105,1,677,4,665,1001,64,1,64,1002,64,2,64,109,-21,2107,26,8,63,1005,63,693,1106,0,699,4,683,1001,64,1,64,1002,64,2,64,109,19,1201,-9,0,63,1008,63,30,63,1005,63,719,1105,1,725,4,705,1001,64,1,64,1002,64,2,64,109,9,1206,-6,741,1001,64,1,64,1106,0,743,4,731,1002,64,2,64,109,-5,2106,0,6,4,749,1001,64,1,64,1105,1,761,1002,64,2,64,109,-14,1202,-1,1,63,1008,63,27,63,1005,63,781,1105,1,787,4,767,1001,64,1,64,1002,64,2,64,109,1,21107,45,44,5,1005,1014,807,1001,64,1,64,1105,1,809,4,793,1002,64,2,64,109,8,21101,46,0,0,1008,1017,46,63,1005,63,835,4,815,1001,64,1,64,1106,0,835,1002,64,2,64,109,-26,2108,20,10,63,1005,63,857,4,841,1001,64,1,64,1106,0,857,1002,64,2,64,109,24,21102,47,1,-5,1008,1010,46,63,1005,63,881,1001,64,1,64,1106,0,883,4,863,1002,64,2,64,109,6,2105,1,3,4,889,1001,64,1,64,1105,1,901,4,64,99,21102,27,1,1,21101,915,0,0,1105,1,922,21201,1,29830,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1105,1,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1105,1,968,21201,-2,0,-2,109,-3,2106,0,0 diff --git a/day09_test.go b/day09_test.go new file mode 100644 index 0000000..5bc4aeb --- /dev/null +++ b/day09_test.go @@ -0,0 +1,21 @@ +package aoc2019 + +import "testing" + +func TestCalculateDay9_Part1(t *testing.T) { + codeP0, err := solveDay9Part1("day09_input.txt") + if err != nil { + t.Fatalf("Day 9 solver failed: %s", err) + } + + t.Logf("Solution Day 9 Part 1: %d", codeP0) +} + +func TestCalculateDay9_Part2(t *testing.T) { + result, err := solveDay9Part2("day09_input.txt") + if err != nil { + t.Fatalf("Day 9 solver failed: %s", err) + } + + t.Logf("Solution Day 9 Part 2: %d", result) +} diff --git a/intcode.go b/intcode.go index 90ba200..455f4e9 100644 --- a/intcode.go +++ b/intcode.go @@ -8,14 +8,15 @@ import ( "github.com/pkg/errors" ) -type opCodeFlag int +type opCodeFlag int64 const ( opCodeFlagPosition opCodeFlag = iota opCodeFlagImmediate + opCodeFlagRelative ) -type opCodeType int +type opCodeType int64 const ( opCodeTypeAddition opCodeType = 1 // Day 02 @@ -26,6 +27,7 @@ const ( opCodeTypeJumpIfFalse opCodeType = 6 // Day 05 P2 opCodeTypeLessThan opCodeType = 7 // Day 05 P2 opCodeTypeEquals opCodeType = 8 // Day 05 P2 + opCodeTypeAdjRelBase opCodeType = 9 // Day 09 opCodeTypeExit opCodeType = 99 // Day 02 ) @@ -34,8 +36,8 @@ type opCode struct { flags []opCodeFlag } -func (o opCode) GetFlag(param int) opCodeFlag { - if param-1 >= len(o.flags) { +func (o opCode) GetFlag(param int64) opCodeFlag { + if param-1 >= int64(len(o.flags)) { return opCodeFlagPosition } return o.flags[param-1] @@ -45,12 +47,12 @@ func (o opCode) eq(in opCode) bool { return o.Type == in.Type && reflect.DeepEqual(o.flags, in.flags) } -func parseOpCode(in int) opCode { +func parseOpCode(in int64) opCode { out := opCode{} out.Type = opCodeType(in % 100) - var paramFactor = 100 + var paramFactor int64 = 100 for { if in < paramFactor { break @@ -63,20 +65,20 @@ func parseOpCode(in int) opCode { return out } -func cloneIntcode(in []int) []int { - out := make([]int, len(in)) +func cloneIntcode(in []int64) []int64 { + out := make([]int64, len(in)) for i, v := range in { out[i] = v } return out } -func parseIntcode(code string) ([]int, error) { +func parseIntcode(code string) ([]int64, error) { parts := strings.Split(code, ",") - var out []int + var out []int64 for _, n := range parts { - v, err := strconv.Atoi(n) + v, err := strconv.ParseInt(n, 10, 64) if err != nil { return nil, err } @@ -86,30 +88,69 @@ func parseIntcode(code string) ([]int, error) { return out, nil } -func executeIntcode(code []int, in, out chan int) ([]int, error) { - var pos int +func executeIntcode(code []int64, in, out chan int64) ([]int64, error) { + var ( + pos int64 + relativeBase int64 + ) if out != nil { defer close(out) } - getParamValue := func(param int, op opCode) int { + transformPos := func(param int64, op opCode, write bool) int64 { + var addr int64 + switch op.GetFlag(param) { case opCodeFlagImmediate: - return code[pos+param] + if write { + addr = code[pos+param] + } else { + addr = pos + param + } case opCodeFlagPosition: - return code[code[pos+param]] + addr = code[pos+param] + + case opCodeFlagRelative: + addr = code[pos+param] + int64(relativeBase) default: panic(errors.Errorf("Unexpected opCodeFlag %d", op.GetFlag(param))) } + + return addr + } + + getParamValue := func(param int64, op opCode) int64 { + var addr = transformPos(param, op, false) + + if addr >= int64(len(code)) { + return 0 + } + + return code[addr] + } + + setParamValue := func(param, value int64, op opCode) { + var addr = transformPos(param, op, false) + + if addr >= int64(len(code)) { + // Write outside memory, increase memory + var tmp = make([]int64, addr+1) + for i, v := range code { + tmp[i] = v + } + code = tmp + } + + code[addr] = value } for { - if pos >= len(code) { + if pos >= int64(len(code)) { return nil, errors.Errorf("Code position out of bounds: %d (len=%d)", pos, len(code)) } @@ -118,15 +159,15 @@ func executeIntcode(code []int, in, out chan int) ([]int, error) { switch op.Type { case opCodeTypeAddition: // p1 + p2 => p3 - code[code[pos+3]] = getParamValue(1, op) + getParamValue(2, op) + setParamValue(3, getParamValue(1, op)+getParamValue(2, op), op) pos += 4 case opCodeTypeMultiplication: // p1 * p2 => p3 - code[code[pos+3]] = getParamValue(1, op) * getParamValue(2, op) + setParamValue(3, getParamValue(1, op)*getParamValue(2, op), op) pos += 4 case opCodeTypeInput: // in => p1 - code[code[pos+1]] = <-in + setParamValue(1, <-in, op) pos += 2 case opCodeTypeOutput: // p1 => out @@ -148,21 +189,25 @@ func executeIntcode(code []int, in, out chan int) ([]int, error) { pos += 3 case opCodeTypeLessThan: // p1 < p2 => p3 - var res int + var res int64 if getParamValue(1, op) < getParamValue(2, op) { res = 1 } - code[code[pos+3]] = res + setParamValue(3, res, op) pos += 4 case opCodeTypeEquals: // p1 == p2 => p3 - var res int + var res int64 if getParamValue(1, op) == getParamValue(2, op) { res = 1 } - code[code[pos+3]] = res + setParamValue(3, res, op) pos += 4 + case opCodeTypeAdjRelBase: + relativeBase += getParamValue(1, op) + pos += 2 + case opCodeTypeExit: // exit return code, nil diff --git a/intcode_test.go b/intcode_test.go index fc2e4d9..36ecdc4 100644 --- a/intcode_test.go +++ b/intcode_test.go @@ -1,9 +1,12 @@ package aoc2019 -import "testing" +import ( + "reflect" + "testing" +) func TestParseOpCode(t *testing.T) { - for code, expOpCode := range map[int]opCode{ + for code, expOpCode := range map[int64]opCode{ 1002: {Type: opCodeTypeMultiplication, flags: []opCodeFlag{opCodeFlagPosition, opCodeFlagImmediate}}, 1101: {Type: opCodeTypeAddition, flags: []opCodeFlag{opCodeFlagImmediate, opCodeFlagImmediate}}, } { @@ -17,9 +20,9 @@ func TestExecuteIntcodeIO(t *testing.T) { code, _ := parseIntcode("3,0,4,0,99") var ( - exp = 25 - in = make(chan int, 1) - out = make(chan int, 1) + exp int64 = 25 + in = make(chan int64, 1) + out = make(chan int64, 1) ) in <- exp @@ -41,8 +44,8 @@ func TestExecuteIntcodeImmediateFlag(t *testing.T) { code, _ := parseIntcode("102,4,7,0,4,0,99,3") var ( - exp = 12 - out = make(chan int, 1) + exp int64 = 12 + out = make(chan int64, 1) ) if _, err := executeIntcode(code, nil, out); err != nil { @@ -60,15 +63,15 @@ func TestExecuteIntcodeEquals(t *testing.T) { "immediate": "3,3,1108,-1,8,3,4,3,99", } { - for input, exp := range map[int]int{ + for input, exp := range map[int64]int64{ 1: 0, 8: 1, 20: 0, -8: 0, } { var ( - in = make(chan int, 1) - out = make(chan int, 10) + in = make(chan int64, 1) + out = make(chan int64, 10) ) code, _ := parseIntcode(codeStr) @@ -93,15 +96,15 @@ func TestExecuteIntcodeLessThan(t *testing.T) { "immediate": "3,3,1107,-1,8,3,4,3,99", } { - for input, exp := range map[int]int{ + for input, exp := range map[int64]int64{ 1: 1, 8: 0, 20: 0, -8: 1, } { var ( - in = make(chan int, 1) - out = make(chan int, 10) + in = make(chan int64, 1) + out = make(chan int64, 10) ) code, _ := parseIntcode(codeStr) @@ -126,13 +129,13 @@ func TestExecuteIntcodeJump(t *testing.T) { "immediate": "3,3,1105,-1,9,1101,0,0,12,4,12,99,1", } { - for input, exp := range map[int]int{ + for input, exp := range map[int64]int64{ 5: 1, 0: 0, } { var ( - in = make(chan int, 1) - out = make(chan int, 10) + in = make(chan int64, 1) + out = make(chan int64, 10) ) code, _ := parseIntcode(codeStr) @@ -150,3 +153,44 @@ func TestExecuteIntcodeJump(t *testing.T) { } } + +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) + } + } +}