Exemplo n.º 1
0
        public async Task <IntcodeProgramResult> RunProgram(IntcodeProgramInput programInput)
        {
            CurrentMemory = new long[InitialMemory.Length * 100];
            InitialMemory.CopyTo(CurrentMemory, 0);
            programInput.MemoryInitialisation(CurrentMemory);

            InstructionPointer = 0;
            RelativeBase       = 0;

            Exited  = false;
            Errored = false;
            Paused  = false;

            Inputs.Clear();
            programInput.Inputs.ForEach(AddInput);

            while (!Exited)
            {
                var operationCode     = (int)(((CurrentMemory[InstructionPointer] / (decimal)100) - Math.Floor(CurrentMemory[InstructionPointer] / (decimal)100)) * (decimal)100);
                var matchedOperations = AvailableOperations.Where(op => op.Code == operationCode);

                if (matchedOperations.Count() == 0)
                {
                    Exited  = true;
                    Errored = true;
                }
                else if (matchedOperations.Count() == 1)
                {
                    try
                    {
                        var operationResult = await matchedOperations.Single().RunOperation(InstructionPointer, CurrentMemory, RelativeBase, GetNextInput);

                        Exited |= operationResult.Exit;
                        if (operationResult.Output.HasValue)
                        {
                            AddOutput(operationResult.Output.Value);
                        }
                        if (operationResult.JumpTo.HasValue)
                        {
                            InstructionPointer = operationResult.JumpTo.Value;
                        }
                        else
                        {
                            InstructionPointer += (1 + (ulong)matchedOperations.Single().ParameterCount);
                        }
                        if (operationResult.AdjustRelativeBase.HasValue)
                        {
                            RelativeBase = RelativeBase + operationResult.AdjustRelativeBase.Value;
                        }
                    }
                    catch (IntcodeOperationException ex)
                    {
                        Exited  = true;
                        Errored = true;
                    }
                }
                else
                {
                    throw new Exception("Multiple operation definitions for operation code: " + CurrentMemory[InstructionPointer]);
                }
            }

            var finalMemState = new long[InitialMemory.Length * 100];

            CurrentMemory.CopyTo(finalMemState, 0);

            List <long> finalOutputs;

            lock (OutputLock)
            {
                finalOutputs = Outputs.CloneAsList().ToList();
            }

            return(new IntcodeProgramResult(!Errored, finalMemState, finalOutputs));
        }