Created
December 9, 2019 23:19
-
-
Save kiroma/7572c32d0f841d276013a9add09d6675 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <vector> | |
#include <string> | |
#include <exception> | |
struct Event | |
{ | |
enum | |
{ | |
none = 0, | |
output = 1, | |
input = 2 | |
}type = none; | |
long long* var = nullptr; | |
operator bool() | |
{ | |
return type != none; | |
} | |
}; | |
constexpr size_t pow(size_t a, size_t b) | |
{ | |
if(b == 0) | |
{ | |
return 1; | |
} | |
size_t res = a; | |
for(size_t i = 1; i < b; ++i) | |
{ | |
res *= a; | |
} | |
return res; | |
} | |
class Intmachine | |
{ | |
public: | |
std::vector<long long> memory; | |
Intmachine(const std::string_view Intcode) | |
{ | |
std::ifstream ifs(Intcode.data()); | |
for(long i; ifs >> i; ifs.ignore()) | |
{ | |
memory.push_back(i); | |
} | |
memory.resize(memory.size() * 128, 0); | |
} | |
size_t relBase = 0; | |
size_t instr_ptr = 0; | |
long long &getVar(unsigned char param) | |
{ | |
unsigned char mode = (memory[instr_ptr]/(10*pow(10, param))) % 10; | |
switch(mode) | |
{ | |
case 0: | |
return memory[memory[instr_ptr + param]]; | |
break; | |
case 1: | |
return memory[instr_ptr + param]; | |
break; | |
case 2: | |
return memory[memory[instr_ptr + param] + relBase]; | |
break; | |
default: | |
std::terminate(); | |
} | |
} | |
Event step() | |
{ | |
switch(memory[instr_ptr]%100) | |
{ | |
case 1: | |
getVar(3) = getVar(1) + getVar(2); | |
instr_ptr += 4; | |
break; | |
case 2: | |
getVar(3) = getVar(1) * getVar(2); | |
instr_ptr += 4; | |
break; | |
case 3: | |
{ | |
Event e{Event::input, &getVar(1)}; | |
instr_ptr += 2; | |
return e; | |
} | |
case 4: | |
{ | |
Event e{Event::output, &getVar(1)}; | |
instr_ptr += 2; | |
return e; | |
} | |
case 5: | |
if(getVar(1)) | |
{ | |
instr_ptr = getVar(2); | |
break; | |
} | |
instr_ptr += 3; | |
break; | |
case 6: | |
if(!getVar(1)) | |
{ | |
instr_ptr = getVar(2); | |
break; | |
} | |
instr_ptr += 3; | |
break; | |
case 7: | |
getVar(3) = getVar(1) < getVar(2); | |
instr_ptr += 4; | |
break; | |
case 8: | |
getVar(3) = getVar(1) == getVar(2); | |
instr_ptr += 4; | |
break; | |
case 9: | |
relBase += getVar(1); | |
instr_ptr += 2; | |
break; | |
default: | |
std::cerr << "Unknown opcode " << memory[instr_ptr] << '\n'; | |
std::terminate(); | |
break; | |
} | |
return Event(); | |
} | |
Event run() | |
{ | |
while(memory[instr_ptr] != 99) | |
{ | |
Event e = step(); | |
if(e.type) | |
{ | |
return e; | |
} | |
} | |
return Event(); | |
} | |
}; | |
int main() | |
{ | |
Intmachine machine("input.txt"); | |
while(Event e = machine.run()) | |
{ | |
if(e.type == Event::input) | |
{ | |
*e.var = 2; | |
} | |
else | |
{ | |
std::cout << *e.var << '\n'; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment