Created
December 5, 2019 23:44
-
-
Save tinylucid/7d30d6a72fa38241b59fad4be9a81091 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 <sstream> | |
#include <fstream> | |
#include <vector> | |
std::vector<int> parse_input(std::string& in, char delimiter = ' ') | |
{ | |
std::vector<int> result; | |
std::stringstream input_stream(in); | |
std::string parsed_number; | |
while (std::getline(input_stream, parsed_number, delimiter)) | |
{ | |
int i = std::stoi(parsed_number); | |
result.push_back(i); | |
} | |
return result; | |
} | |
int get_instruction_mode(const std::vector<int>& memory, int ip, bool immediate) { | |
if (immediate) { | |
return ip; | |
} | |
return memory[ip]; | |
} | |
void execute_program(std::vector<int>& code, const int input) | |
{ | |
auto ip = code.begin(); | |
while (ip != code.end()) | |
{ | |
const int opcode = *(ip++); | |
const int instruction = opcode % 100; | |
const bool mode_for_opA = ((opcode / 100) % 10) == 1; | |
const bool mode_for_opB = ((opcode / 1000) % 10) == 1; | |
switch (instruction) | |
{ | |
case 99: // halt | |
{ | |
return; | |
} | |
case 1: // add | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
const int opB = get_instruction_mode(code, *(ip++), mode_for_opB); | |
const int opC = *(ip++); | |
code[opC] = opA + opB; | |
break; | |
} | |
case 2: // mul | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
const int opB = get_instruction_mode(code, *(ip++), mode_for_opB); | |
const int opC = *(ip++); | |
code[opC] = opA * opB; | |
break; | |
} | |
case 3: // input | |
{ | |
const int opA = *(ip++); | |
code[opA] = input; | |
break; | |
} | |
case 4: // print | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
std::cout << opA << std::endl; | |
break; | |
} | |
case 5: // jump if not zero | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
const int opB = get_instruction_mode(code, *(ip++), mode_for_opB); | |
if (opA != 0) | |
ip = code.begin() + opB; | |
break; | |
} | |
case 6: // jump if zero | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
const int opB = get_instruction_mode(code, *(ip++), mode_for_opB); | |
if (opA == 0) | |
ip = code.begin() + opB; | |
break; | |
} | |
case 7: // less than | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
const int opB = get_instruction_mode(code, *(ip++), mode_for_opB); | |
const int opC = *(ip++); | |
if (opA < opB) | |
code[opC] = 1; | |
else | |
code[opC] = 0; | |
break; | |
} | |
case 8: | |
{ | |
const int opA = get_instruction_mode(code, *(ip++), mode_for_opA); | |
const int opB = get_instruction_mode(code, *(ip++), mode_for_opB); | |
const int opC = *(ip++); | |
if (opA == opB) | |
code[opC] = 1; | |
else | |
code[opC] = 0; | |
break; | |
} | |
default: | |
throw std::exception{ "intruction with wrong opcode " }; | |
} | |
} | |
} | |
int main() | |
{ | |
std::ifstream file_stream("input.txt"); | |
std::string main_input((std::istreambuf_iterator<char>(file_stream)), | |
(std::istreambuf_iterator<char>())); | |
std::vector<int> main_program = parse_input(main_input, ','); | |
//execute_program(main_program, 1); // part 1 | |
execute_program(main_program, 5); // part 2 | |
#if (0) | |
for (auto const& value : main_program) | |
{ | |
std::cout << value << " "; | |
} | |
#endif | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment