Last active
December 5, 2019 18:08
-
-
Save invakid404/96d02d6d741e5a94313c9380829d2bf0 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
/* | |
* =========================================================================== | |
* | |
* Filename: day5.cpp | |
* | |
* Description: Day 5 of Advent of Code solution | |
* | |
* Version: 1.0 | |
* Created: 12/5/2019 6:41:38 PM | |
* Revision: none | |
* Compiler: gcc | |
* | |
* Author: invakid404 | |
* | |
* ============================================================================ | |
*/ | |
#include <bits/stdc++.h> | |
#define ENDL '\n'; | |
#define IN_PATH R"(D:\Coding\Problems\adventofcode\in\day5.txt)" | |
namespace { | |
class computer; | |
auto split(const std::string& s, char d) -> std::vector<std::string> { | |
std::vector<std::string> result; | |
std::stringstream ss(s); | |
std::string curr; | |
while(std::getline(ss, curr, d)) { | |
result.emplace_back(curr); | |
} | |
return result; | |
} | |
auto extract_digits(int& n, int l = 1) -> int { | |
auto p = std::pow(10, l); | |
auto d = std::div(n, p); | |
n = d.quot; | |
return d.rem; | |
} | |
typedef std::vector<int> computer_memory; | |
typedef std::function<void(computer*)> opcode_function; | |
typedef std::unordered_map<int, opcode_function> computer_opcodes; | |
class computer { | |
public: | |
computer(const std::string& data) { | |
auto parts = split(data, ','); | |
this->memory.resize(parts.size()); | |
std::transform( | |
parts.begin(), parts.end(), | |
this->memory.begin(), | |
[](const auto& val) { | |
return std::stoi(val); | |
} | |
); | |
} | |
auto define_opcode(int id, opcode_function op) -> void { | |
this->opcodes[id] = op; | |
} | |
auto execute() -> void { | |
this->rip = 0; | |
while(this->rip < this->memory.size()) { | |
auto mem_val = this->memory[this->rip]; | |
auto op_id = extract_digits(mem_val, 2); | |
if(op_id == 99) { | |
break; | |
} | |
for(auto i = 1; i <= 3; ++i) { | |
auto curr = extract_digits(mem_val); | |
this->param_state[i] = curr; | |
} | |
this->opcodes[op_id](this); | |
} | |
} | |
auto jump_to(int n) -> void { | |
this->rip = n; | |
} | |
auto step_forward(int n) -> void { | |
this->rip += n; | |
} | |
auto get_param(int offset, bool ignore = false) -> int { | |
auto val = this->memory[this->rip + offset]; | |
return param_state[offset] == 0 && !ignore | |
? this->memory[val] | |
: val; | |
} | |
auto set_memory(int val, int offset) -> void { | |
this->memory[offset] = val; | |
} | |
private: | |
computer_memory memory; | |
computer_opcodes opcodes; | |
std::size_t rip; | |
int param_state[4]; | |
}; | |
auto add_opcode(computer* comp) -> void { | |
auto a = comp->get_param(1); | |
auto b = comp->get_param(2); | |
auto dest = comp->get_param(3, true); | |
comp->set_memory(a + b, dest); | |
comp->step_forward(4); | |
} | |
auto mult_opcode(computer* comp) -> void { | |
auto a = comp->get_param(1); | |
auto b = comp->get_param(2); | |
auto dest = comp->get_param(3, true); | |
comp->set_memory(a * b, dest); | |
comp->step_forward(4); | |
} | |
auto read_opcode(computer* comp) -> void { | |
auto dest = comp->get_param(1, true); | |
int val; | |
std::cin >> val; | |
comp->set_memory(val, dest); | |
comp->step_forward(2); | |
} | |
auto print_opcode(computer* comp) -> void { | |
auto val = comp->get_param(1); | |
std::cout << val << ENDL; | |
comp->step_forward(2); | |
} | |
auto jump_if_true_opcode(computer* comp) -> void { | |
auto val = comp->get_param(1); | |
if(val) { | |
auto jmp = comp->get_param(2); | |
comp->jump_to(jmp); | |
} else { | |
comp->step_forward(3); | |
} | |
} | |
auto jump_if_false_opcode(computer* comp) -> void { | |
auto val = comp->get_param(1); | |
if(!val) { | |
auto jmp = comp->get_param(2); | |
comp->jump_to(jmp); | |
} else { | |
comp->step_forward(3); | |
} | |
} | |
auto less_than_opcode(computer* comp) -> void { | |
auto a = comp->get_param(1); | |
auto b = comp->get_param(2); | |
auto dest = comp->get_param(3, true); | |
comp->set_memory(a < b ? 1 : 0, dest); | |
comp->step_forward(4); | |
} | |
auto equals_opcode(computer* comp) -> void { | |
auto a = comp->get_param(1); | |
auto b = comp->get_param(2); | |
auto dest = comp->get_param(3, true); | |
comp->set_memory(a == b ? 1 : 0, dest); | |
comp->step_forward(4); | |
} | |
} | |
int main() { | |
std::ifstream f_in; | |
f_in.open(IN_PATH); | |
if(!f_in) { | |
std::cerr << "Failed to open file!" << ENDL; | |
return 1; | |
} | |
std::string data; | |
std::getline(f_in, data); | |
auto comp = computer(data); | |
comp.define_opcode(1, add_opcode); | |
comp.define_opcode(2, mult_opcode); | |
comp.define_opcode(3, read_opcode); | |
comp.define_opcode(4, print_opcode); | |
comp.define_opcode(5, jump_if_true_opcode); | |
comp.define_opcode(6, jump_if_false_opcode); | |
comp.define_opcode(7, less_than_opcode); | |
comp.define_opcode(8, equals_opcode); | |
comp.execute(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment