Exemplo n.º 1
0
    /// <summary>Runs the IntCode in memory.
    /// </summary>
    public void Run()
    {
        if (State == IntCodeState.Finished)
        {
            throw new ApplicationException("Already finished");
        }
        if (State == IntCodeState.NeedsInput && inputBuffer.Count == 0)
        {
            throw new ApplicationException("Needs Input");
        }

        State = IntCodeState.Running;

        while (State == IntCodeState.Running)
        {
            ReadInstruction();

            if (!OpCodesDict.ContainsKey(opCode))
            {
                throw new ApplicationException($"Unknown OpCode '{opCode}'.");
            }

            var opCodeAction = OpCodesDict[opCode];
            opCodeAction.Invoke(this, null);

            AfterRunStep?.Invoke(this, null);
        }
    }
Exemplo n.º 2
0
 /// <summary>
 /// If the condition is fulfilled, jumps to a new memory address - if not, proceeds as normal through the code.
 /// Condition is based on a single parameter
 /// </summary>
 public static IntCodeState JumpIf(this IntCodeState state, Func <long, bool> shouldJump)
 {
     return(new IntCodeState(state)
     {
         State = state.State,
         Index = shouldJump(state.ReadParameter(1)) ? (int)state.ReadParameter(2) : state.Index + 3
     });
 }
Exemplo n.º 3
0
 /// <summary>
 /// Accepts a single input, applying it to the memory address stored at the single parameter.
 /// </summary>
 public static IntCodeState ApplyInput(this IntCodeState state, long input)
 {
     return(new IntCodeState(state)
     {
         State = state.SetAt(state.WriteParameter(1), input),
         Index = state.Index + 2
     });
 }
Exemplo n.º 4
0
 /// <summary>
 /// Outputs the value of the single parameter.
 /// Outputs are not tracked within the intCode state, so a callback is used to apply it as necessary
 /// </summary>
 public static IntCodeState ApplyOutput(this IntCodeState state, Action <long> applyOutput)
 {
     applyOutput(state.ReadParameter(1));
     return(new IntCodeState(state)
     {
         State = state.State,
         Index = state.Index + 2
     });
 }
Exemplo n.º 5
0
        public static IntCodeState AdjustRelativeBase(this IntCodeState state)
        {
            var baseChange = state.ReadParameter(1);

            return(new IntCodeState(state)
            {
                Index = state.Index + 2,
                RelativeBase = state.RelativeBase + baseChange
            });
        }
Exemplo n.º 6
0
        /// <summary>
        /// Compares the first two values using the given comparator.
        /// Sets the value in the index given by param 3 to either 1 or 0, reflecting the result of the comparison
        /// </summary>
        public static IntCodeState Compare(this IntCodeState state, Func <long, long, bool> comparator)
        {
            var valueToStore = comparator(state.ReadParameter(1), state.ReadParameter(2)) ? 1 : 0;

            return(new IntCodeState(state)
            {
                State = state.SetAt(state.WriteParameter(3), valueToStore),
                Index = state.Index + 4
            });
        }
Exemplo n.º 7
0
        /// <summary>
        /// Applies an arbitrary operation to the first *TWO* parameters, outputting based on the third parameter.
        /// Will need extending if it needs to be applied to more than two parameters.
        /// </summary>
        public static IntCodeState ApplyOperation(this IntCodeState state, Func <long, long, long> operation)
        {
            var operationResult = operation(state.ReadParameter(1), state.ReadParameter(2));

            return(new IntCodeState(state)
            {
                State = state.SetAt(state.WriteParameter(3), operationResult),
                Index = state.Index + 4
            });
        }
Exemplo n.º 8
0
    void OP_Input()
    {
        var check = inputBuffer.TryDequeue(out long value);

        if (!check)
        {
            State = IntCodeState.NeedsInput;
            return;
        }

        WriteMemory(AddressPointer + 1, value, GetParameterMode(1));
        MoveToNext(2);
    }
Exemplo n.º 9
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
            });
        }
Exemplo n.º 10
0
 void OP_Halt()
 {
     State = IntCodeState.Finished;
     MoveToNext(1);
 }