AoC code coverage
Current view: top level - aoclib - Intcode.cpp (source / functions) Coverage Total Hit
Test: master Lines: 94.8 % 116 110
Test Date: 2025-07-28 10:53:57 Functions: 100.0 % 12 12

            Line data    Source code
       1              : #include "Intcode.h"
       2              : 
       3              : #include "IntegerCast.h"
       4              : #include "Parsing.h"
       5              : 
       6              : namespace {
       7              : static constexpr std::array<int64_t, 10u> paramFactor = {
       8              :     -1, 100, 1000, 10000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000};
       9              : }
      10              : 
      11              : Computer::Computer(std::string_view const programString)
      12           23 :     : _memory(parseIntegerRange<int64_t>(programString)) {}
      13              : 
      14        30286 : Computer::Status Computer::run() {
      15      1426826 :   while (performOp())
      16      1396540 :     ;
      17        30286 :   return _status;
      18        30286 : }
      19              : 
      20         5313 : void Computer::reset() {
      21         5313 :   _ip = 0;
      22         5313 :   _rb = 0;
      23         5432 :   while (!_inputs.empty())
      24          119 :     _inputs.pop();
      25         5313 : }
      26              : 
      27        27489 : void Computer::queueInput(int64_t value) { _inputs.push(value); }
      28              : 
      29         5313 : void Computer::reset(std::vector<int64_t> const &memory) {
      30         5313 :   reset();
      31         5313 :   setMemory(memory);
      32         5313 : }
      33              : 
      34      1426826 : int64_t Computer::opcode(Address address) { return readMemory(address) % 100; }
      35              : 
      36      3274708 : int64_t Computer::parameterMode(Address address, size_t param) {
      37      3274708 :   return readMemory(address) / paramFactor[param] % 10;
      38      3274708 : }
      39              : 
      40       853624 : void Computer::writeMemory(Address address, int64_t value) {
      41       853624 :   if (address >= _memory.size())
      42         1841 :     _memory.resize(address + 1, 0);
      43       853624 :   _memory[address] = value;
      44       853624 : }
      45              : 
      46      9288759 : int64_t Computer::readMemory(Address address) {
      47      9288759 :   if (address >= _memory.size())
      48            5 :     _memory.resize(address + 1, 0);
      49      9288759 :   return _memory[address];
      50      9288759 : }
      51              : 
      52      1426826 : bool Computer::performOp() {
      53      1426826 :   int64_t value = 0;
      54      1426826 :   switch (opcode()) {
      55       500848 :   case 1: // add
      56       500848 :     writeParam(3, readParam(1) + readParam(2));
      57       500848 :     _ip += 4u;
      58       500848 :     break;
      59       208992 :   case 2: // multiply
      60       208992 :     writeParam(3, readParam(1) * readParam(2));
      61       208992 :     _ip += 4u;
      62       208992 :     break;
      63        52332 :   case 3: // input
      64        52332 :     if (_inputs.empty()) {
      65        24963 :       _status = PAUSED;
      66        24963 :       return false;
      67        24963 :     }
      68        27369 :     writeParam(1, _inputs.front());
      69        27369 :     _inputs.pop();
      70        27369 :     _ip += 2u;
      71        27369 :     break;
      72        89641 :   case 4: // output
      73        89641 :     value = readParam(1);
      74        89641 :     for (auto const &f : _output)
      75        90841 :       f(value);
      76        89641 :     _ip += 2u;
      77        89641 :     break;
      78       203778 :   case 5: // jump if true
      79       203778 :     if (readParam(1) != 0)
      80       155858 :       _ip = readParam(2);
      81        47920 :     else
      82        47920 :       _ip += 3;
      83       203778 :     break;
      84       117631 :   case 6: // jump if false
      85       117631 :     if (readParam(1) == 0)
      86        86258 :       _ip = readParam(2);
      87        31373 :     else
      88        31373 :       _ip += 3;
      89       117631 :     break;
      90        60070 :   case 7: // less than
      91        60070 :     writeParam(3, readParam(1) < readParam(2) ? 1 : 0);
      92        60070 :     _ip += 4u;
      93        60070 :     break;
      94        48116 :   case 8: // equals
      95        48116 :     writeParam(3, readParam(1) == readParam(2) ? 1 : 0);
      96        48116 :     _ip += 4u;
      97        48116 :     break;
      98       140095 :   case 9: // adjust relative base
      99       140095 :     _rb += readParam(1);
     100       140095 :     _ip += 2u;
     101       140095 :     break;
     102         5323 :   case 99:
     103         5323 :     _status = HALTED;
     104         5323 :     return false;
     105            0 :   default:
     106            0 :     ASSERT(false, "Invalid OP code", opcode());
     107      1426826 :   };
     108      1396540 :   return true;
     109      1426826 : }
     110              : 
     111      2429313 : int64_t Computer::readParam(size_t param) {
     112      2429313 :   DEBUG_ASSERT(_ip + param < _memory.size());
     113              : 
     114      2429313 :   int64_t const mode = parameterMode(param);
     115      2429313 :   switch (mode) {
     116       903302 :   case 0: // position mode
     117       903302 :     return readMemory(readMemory(_ip + param));
     118      1120953 :   case 1: // immediate mode
     119      1120953 :     return readMemory(_ip + param);
     120       405058 :   case 2: // relative mode
     121       405058 :     return readMemory(_rb + readMemory(_ip + param));
     122            0 :   default:
     123            0 :     ASSERT(false, "Invalid parameter mode", mode);
     124            0 :     return 0;
     125      2429313 :   }
     126      2429313 : }
     127              : 
     128       845395 : void Computer::writeParam(size_t param, int64_t value) {
     129       845395 :   int64_t const mode = parameterMode(param);
     130       845395 :   switch (mode) {
     131       565669 :   case 0: // position mode
     132       565669 :     writeMemory(readMemory(_ip + param), value);
     133       565669 :     break;
     134       279726 :   case 2: // relative mode
     135       279726 :     writeMemory(_rb + readMemory(_ip + param), value);
     136       279726 :     break;
     137            0 :   default:
     138              :     ASSERT(false, "Invalid parameter mode", mode);
     139       845395 :   }
     140       845395 : }
        

Generated by: LCOV version 2.0-1