public ICCOutput IntCodeComputer() { //InitMemory(); int jumpIndex = 0; inputCallBacks = 0; ICCOutput iccMainOutput = new ICCOutput(); while (jumpIndex <= opCodeSequence.Length) { ICCOutput temp = new ICCOutput(); temp = ProcessOptCode(ref opCodeSequence, ref jumpIndex); //iccMainOutput.opCodeDetected = temp.opCodeDetected; if (temp.opCodeDetected == OpCodes.output) { iccMainOutput.outputFromPhase = temp.outputFromPhase; //break; } else if (temp.opCodeDetected == OpCodes.halt || temp.opCodeDetected == OpCodes.unexpectedHalt) { Debug.WriteLine(temp.outputFromPhase); iccMainOutput.opCodeDetected = OpCodes.halt; break; } } return(iccMainOutput); }
public ICCOutput ProcessOptCode(ref int[] opCodeSeq, ref int instructionStart) { try { ICCOutput outputStruct = new ICCOutput(); //new route is ABCDE //before we do the operation. We must work out what mode we are in. int pos1, pos2, pos3; int sequenceSize = opCodeSeq.Length - 1; pos3 = (instructionStart + 3) <= sequenceSize ? opCodeSeq[instructionStart + 3] : 0; pos2 = instructionStart + 2 <= sequenceSize ? opCodeSeq[instructionStart + 2] : 0; pos1 = instructionStart + 1 <= sequenceSize ? opCodeSeq[instructionStart + 1] : 0; var opCodeAndParamModeList = ProcessInstruction(opCodeSeq[instructionStart]); int val1, val2, val3; switch (opCodeAndParamModeList.Item1) { case OpCodes.add: val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); val2 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); val3 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[2], opCodeSeq, pos3); //moves by 4 params. //Work out what the mode is, then perform the operation. opCodeSeq[pos3] = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1) + RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); instructionStart += 4; outputStruct.opCodeDetected = OpCodes.add; break; case OpCodes.times: val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); val2 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); val3 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[2], opCodeSeq, pos3); //moves by 4 params opCodeSeq[pos3] = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1) * RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); instructionStart += 4; outputStruct.opCodeDetected = OpCodes.times; break; case OpCodes.input: if (manualInputs.Count > 0) { opCodeSeq[pos1] = manualInputs.Dequeue(); instructionStart += 2; } break; case OpCodes.output: val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); instructionStart += 2; outputStruct.opCodeDetected = OpCodes.output; outputStruct.outputFromPhase = val1; break; case OpCodes.jumpIfTrue: //Opcode 5 is jump-if-true: if the first parameter is non-zero, //it sets the instruction pointer to the value from the second parameter. Otherwise, it does nothing. val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); if (Math.Abs(val1) > 0) { val2 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); instructionStart = val2; } else { instructionStart += 3; } outputStruct.opCodeDetected = OpCodes.jumpIfTrue; break; case OpCodes.jumpIfFalse: //Opcode 6 is jump-if-false: if the first parameter is zero, //it sets the instruction pointer to the value from the second parameter. Otherwise, it does nothing. val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); if (val1 == 0) { val2 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); instructionStart = val2; } else { instructionStart += 3; } outputStruct.opCodeDetected = OpCodes.jumpIfFalse; break; case OpCodes.isLessThan: //Opcode 7 is less than: if the first parameter is less than the second parameter, //it stores 1 in the position given by the third parameter. Otherwise, it stores 0. val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); val2 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); val3 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[2], opCodeSeq, pos3); opCodeSeq[pos3] = val1 < val2 ? 1 : 0; instructionStart += 4; outputStruct.opCodeDetected = OpCodes.isLessThan; break; case OpCodes.isEquals: //Opcode 8 is equals: if the first parameter is equal to the second parameter, //it stores 1 in the position given by the third parameter. Otherwise, it stores 0. val1 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[0], opCodeSeq, pos1); val2 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[1], opCodeSeq, pos2); val3 = RetrieveValueBasedOnMode(opCodeAndParamModeList.Item2[2], opCodeSeq, pos3); opCodeSeq[pos3] = val1 == val2 ? 1 : 0; instructionStart += 4; outputStruct.opCodeDetected = OpCodes.isEquals; break; case OpCodes.halt: outputStruct.opCodeDetected = OpCodes.halt; break; } return(outputStruct); } catch (Exception exc) { Debug.WriteLine(exc.Message); ICCOutput oc = new ICCOutput(); oc.opCodeDetected = OpCodes.unexpectedHalt; return(oc); } }