Exemplo n.º 1
0
        public static IEnumerator <IntCodeOutput> ParseAndRunIntCode(
            string intCode,
            Queue <long> inputs  = null,
            long?noun            = null,
            long?verb            = null,
            Func <long> getInput = null)
        {
            long GetNextInput()
            {
                if (inputs.Any())
                {
                    return(inputs.Dequeue());
                }

                if (getInput != null)
                {
                    return(getInput());
                }

                throw new Exception("Cannot fetch new input - queue empty and no input provider present.");
            }

            inputs ??= new Queue <long>();
            var initialState = Parser.ParseIntCode(intCode);

            var state = new IntCodeState
            {
                State = initialState.ApplyNounAndVerb(noun, verb),
                Index = 0
            };
            var outputs = new List <long>();

            while (state.OpCode != 99)
            {
                switch (state.OpCode)
                {
                // ADD
                case 1:
                    state = state.ApplyOperation((x, y) => x + y);
                    break;

                // MULTIPLY
                case 2:
                    state = state.ApplyOperation((x, y) => x * y);
                    break;

                // INPUT
                case 3:
                    state = state.ApplyInput(GetNextInput());
                    break;

                // OUTPUT
                case 4:
                    state = state.ApplyOutput(x => { outputs.Add(x); });
                    yield return(new IntCodeOutput
                    {
                        Output = outputs.Last(), IsComplete = false, CurrentState = state.State
                    });

                    break;

                // JUMP IF TRUE
                case 5:
                    state = state.JumpIf(x => x != 0);
                    break;

                // JUMP IF FALSE
                case 6:
                    state = state.JumpIf(x => x == 0);
                    break;

                // LESS THAN
                case 7:
                    state = state.Compare((x, y) => x < y);
                    break;

                // EQUALS
                case 8:
                    state = state.Compare((x, y) => x == y);
                    break;

                // EQUALS
                case 9:
                    state = state.AdjustRelativeBase();
                    break;

                default:
                    throw new Exception($"Unrecognised instruction: {state.Value}");
                }
            }

            yield return(new IntCodeOutput {
                IsComplete = true, CurrentState = state.State
            });
        }