コード例 #1
0
        public IntcodeProgramStatus RunProgram()
        {
            IntcodeProgramStatus status = IntcodeProgramStatus.Running;

            while (true)
            {
                LogDebugMessage($"Pos: {_position.ToString("0000")}, Cmd: {_program[_position]}");
                var parsedCommand = ParseCommand(_program[_position]);
                var opcode        = parsedCommand[0];
                if (opcode == 1)
                {
                    // Add param1 + param2, store in address pointed to by param3
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3 = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    SetMemoryValue(val3, val1 + val2);
                    _position += 4;
                }
                else if (opcode == 2)
                {
                    // Multiply param1 * param2, store in address pointed to by param3
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3 = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    SetMemoryValue(val3, val1 * val2);
                    _position += 4;
                }
                else if (opcode == 3)
                {
                    // Take user input, and store in the parameter location
                    // If the input provider doesn't have any input,
                    // then pause the program and return awaiting input status
                    if (!_inputProvider.HasInput())
                    {
                        status = IntcodeProgramStatus.AwaitingInput;
                        break;
                    }
                    BigInteger input = _inputProvider.GetInput();
                    var        val1  = GetParameterWritePosition(_position + 1, 1, parsedCommand);
                    SetMemoryValue(val1, input);
                    _position += 2;
                }
                else if (opcode == 4)
                {
                    // Output a value
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    _outputListener.SendOutput(val1);
                    _position += 2;
                }
                else if (opcode == 5)
                {
                    // 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.
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    if (val1 != 0)
                    {
                        _position = GetMemoryAddress(val2);
                    }
                    else
                    {
                        _position += 3;
                    }
                }
                else if (opcode == 6)
                {
                    // 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.
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    if (val1 == 0)
                    {
                        _position = GetMemoryAddress(val2);
                    }
                    else
                    {
                        _position += 3;
                    }
                }
                else if (opcode == 7)
                {
                    // 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.
                    var val1       = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2       = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3       = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    var valToStore = val1 < val2 ? 1 : 0;
                    SetMemoryValue(val3, valToStore);
                    _position += 4;
                }
                else if (opcode == 8)
                {
                    // 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.
                    var val1       = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2       = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3       = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    var valToStore = val1 == val2 ? 1 : 0;
                    SetMemoryValue(val3, valToStore);
                    _position += 4;
                }
                else if (opcode == 9)
                {
                    // Opcode 9 adjusts the relative base by the value of its
                    // only parameter. The relative base increases (or
                    // decreases, if the value is negative) by the value of the
                    // parameter.
                    // For example, if the relative base is 2000, then after
                    // the instruction 109,19, the relative base would be 2019.
                    // If the next instruction were 204,-34, then the value at
                    // address 1985 would be output.
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    _relativeBase += GetMemoryAddress(val1);
                    _position     += 2;
                }
                else if (opcode == 99)
                {
                    status = IntcodeProgramStatus.Completed;
                    break;
                }
                else if (opcode != 99)
                {
                    throw new Exception($"Invalid opcode {_program[_position]} at position {_position}");
                }
            }
            return(status);
        }