Skip to content

Instantly share code, notes, and snippets.

@invakid404
Last active December 5, 2019 18:08
Show Gist options
  • Save invakid404/96d02d6d741e5a94313c9380829d2bf0 to your computer and use it in GitHub Desktop.
Save invakid404/96d02d6d741e5a94313c9380829d2bf0 to your computer and use it in GitHub Desktop.
/*
* ===========================================================================
*
* 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