public void ProcessIntcodeUntilOutput() { while (Count < Intcode.Length) { if (Intcode[Count] == 99) { HitOpcode99 = true; return; } IntcodeInstruction instructions = GetInstructions(Intcode[Count]); if (instructions.Opcode == OpcodeEnum.Input && UsedSecondInputValue) { UsedSecondInputValue = false; return; } ProcessInstructions(instructions, Count); if (instructions.UseIndexForNextInstruction) { Count = instructions.IndexForNextInstruction; } else { Count += instructions.IndexesToMoveForNextInstruction; } } }
public void ProcessAllIntcode() { int count = 0; while (count < Intcode.Length) { if (Intcode[count] == 99) { HitOpcode99 = true; return; } IntcodeInstruction instructions = GetInstructions(Intcode[count]); ProcessInstructions(instructions, count); if (instructions.UseIndexForNextInstruction) { count = instructions.IndexForNextInstruction; } else { count += instructions.IndexesToMoveForNextInstruction; } } }
private void InputBatchOfIntcode(int index, IntcodeInstruction instructions) { InputIterations++; int saveToPosition = Intcode[index + 1]; Intcode[saveToPosition] = InputIterations > 1 ? SecondInputValue : PhaseSetting; instructions.IndexesToMoveForNextInstruction = 2; UsedSecondInputValue = InputIterations > 1; }
private void MultiplyBatchOfIntcode(int index, IntcodeInstruction instructions) { int firstMultNum = instructions.FirstParameterMode == ParameterModesEnum.Position ? Intcode[Intcode[index + 1]] : Intcode[index + 1]; int secondMultNum = instructions.SecondParameterMode == ParameterModesEnum.Position ? Intcode[Intcode[index + 2]] : Intcode[index + 2]; int product = firstMultNum * secondMultNum; Intcode[Intcode[index + 3]] = product; instructions.IndexesToMoveForNextInstruction = 4; }
private void AddBatchOfIntcode(int index, IntcodeInstruction instructions) { int firstAddNum = instructions.FirstParameterMode == ParameterModesEnum.Position ? Intcode[Intcode[index + 1]] : Intcode[index + 1]; int secondAddNum = instructions.SecondParameterMode == ParameterModesEnum.Position ? Intcode[Intcode[index + 2]] : Intcode[index + 2]; int sum = firstAddNum + secondAddNum; Intcode[Intcode[index + 3]] = sum; instructions.IndexesToMoveForNextInstruction = 4; }
private void OutputBatchOfIntcode(int index, IntcodeInstruction instructions) { int outputValue; if (instructions.FirstParameterMode == ParameterModesEnum.Position) { outputValue = Intcode[Intcode[index + 1]]; } else { outputValue = Intcode[index + 1]; } OutputData.Add(outputValue); instructions.IndexesToMoveForNextInstruction = 2; }
private void EqualsBatchOfIntcode(int index, IntcodeInstruction instructions) { int firstParam = instructions.FirstParameterMode == ParameterModesEnum.Immediate ? Intcode[index + 1] : Intcode[Intcode[index + 1]]; int secondParam = instructions.SecondParameterMode == ParameterModesEnum.Immediate ? Intcode[index + 2] : Intcode[Intcode[index + 2]]; int thirdParam = Intcode[index + 3]; if (firstParam == secondParam) { Intcode[thirdParam] = 1; } else { Intcode[thirdParam] = 0; } instructions.IndexesToMoveForNextInstruction = 4; }
public void JumpIfFalseBatchOfIntcode(int index, IntcodeInstruction instructions) { int firstParam = instructions.FirstParameterMode == ParameterModesEnum.Immediate ? Intcode[index + 1] : Intcode[Intcode[index + 1]]; int secondParam = instructions.SecondParameterMode == ParameterModesEnum.Immediate ? Intcode[index + 2] : Intcode[Intcode[index + 2]]; if (firstParam == 0) { Intcode[index] = secondParam; instructions.IndexForNextInstruction = secondParam; instructions.UseIndexForNextInstruction = true; } else { instructions.IndexesToMoveForNextInstruction = 3; } }
private static IntcodeInstruction GetInstructions(int input) { string inputStr = input.ToString(); int lengthOfInput = inputStr.Length; IntcodeInstruction instructions; // I'd prefer a more robust solution than what is below OpcodeEnum opcode; ParameterModesEnum firstParameterMode; ParameterModesEnum secondParameterMode; ParameterModesEnum thirdParameterMode; switch (lengthOfInput) { case 1: opcode = GetOpcode(input); instructions = new IntcodeInstruction(opcode, ParameterModesEnum.Position, ParameterModesEnum.Position, ParameterModesEnum.Position); return(instructions); case 3: opcode = GetOpcode(Int32.Parse(inputStr[2].ToString())); firstParameterMode = GetParameter(Int32.Parse(inputStr[0].ToString())); instructions = new IntcodeInstruction(opcode, firstParameterMode, ParameterModesEnum.Position, ParameterModesEnum.Position); return(instructions); case 4: opcode = GetOpcode(Int32.Parse(inputStr[3].ToString())); firstParameterMode = GetParameter(Int32.Parse(inputStr[1].ToString())); secondParameterMode = GetParameter(Int32.Parse(inputStr[0].ToString())); instructions = new IntcodeInstruction(opcode, firstParameterMode, secondParameterMode, ParameterModesEnum.Position); return(instructions); case 5: opcode = GetOpcode(Int32.Parse(inputStr[4].ToString())); firstParameterMode = GetParameter(Int32.Parse(inputStr[2].ToString())); secondParameterMode = GetParameter(Int32.Parse(inputStr[1].ToString())); thirdParameterMode = GetParameter(Int32.Parse(inputStr[0].ToString())); instructions = new IntcodeInstruction(opcode, firstParameterMode, secondParameterMode, thirdParameterMode); return(instructions); default: throw new Exception("Invalid lenght of instructions"); } }
private void ProcessInstructions(IntcodeInstruction instructions, int currentIndex) { // strategy pattern would be cleaner switch (instructions.Opcode) { case OpcodeEnum.Add: AddBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.Multiply: MultiplyBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.Input: InputBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.Output: OutputBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.JumpIfTrue: JumpIfTrueBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.JumpIfFalse: JumpIfFalseBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.LessThan: LessThanBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.Equals: EqualsBatchOfIntcode(currentIndex, instructions); break; case OpcodeEnum.EndProgram: break; default: throw new Exception("Invalid opcode"); } }