From 6bdb425c37b0e532d94f5b5cb214c22d3744bb47 Mon Sep 17 00:00:00 2001 From: Carl Westerlund Date: Thu, 5 Dec 2019 20:25:26 +0000 Subject: [PATCH] Solutions for day 5 in C++ --- nerarith-c++/day5/5a.cpp | 138 ++++++++++++++++++++++++++++ nerarith-c++/day5/5b.cpp | 194 +++++++++++++++++++++++++++++++++++++++ nerarith-c++/day5/input | 1 + nerarith-c++/day5/run_5a | 2 + nerarith-c++/day5/run_5b | 2 + 5 files changed, 337 insertions(+) create mode 100644 nerarith-c++/day5/5a.cpp create mode 100644 nerarith-c++/day5/5b.cpp create mode 100644 nerarith-c++/day5/input create mode 100755 nerarith-c++/day5/run_5a create mode 100755 nerarith-c++/day5/run_5b diff --git a/nerarith-c++/day5/5a.cpp b/nerarith-c++/day5/5a.cpp new file mode 100644 index 0000000..f47990d --- /dev/null +++ b/nerarith-c++/day5/5a.cpp @@ -0,0 +1,138 @@ +#include +#include "prettyprint.hpp" +using namespace std; + +const int MAX_NUM_PARAMETERS = 3; + +set known_opcodes = {1, 2, 3, 4, 99}; +map num_parameters_for_opcode = { + {1, 3}, + {2, 3}, + {3, 1}, + {4, 1}, + {99, 0} +}; +vector memory; +int memory_size; +int memory_get (int address) { + if (0 <= address && address < memory_size) + return memory[address]; + else { + cerr << "error: out of bounds with address " << address << endl; + return -1; + } +} +void memory_set (int address, int value) { + if (0 <= address && address < memory_size) + memory[address] = value; + else + cerr << "error: out of bounds with address " << address << endl; +} + +pair> extract_opcode_parameter_modes (int address) { + int combined = memory_get(address); + int opcode = combined % 100; + combined /= 100; + vector parameter_modes (3); + for (int i=0; i < MAX_NUM_PARAMETERS; i++) { + parameter_modes[i] = combined % 10; + combined /= 10; + } + return {opcode, parameter_modes}; +} + +const int PARAMETER_MODE_POSITION = 0; +const int PARAMETER_MODE_IMMEDIATE = 1; + +vector get_parameters (int address, int num_parameters, vector parameter_modes) { + vector parameter_addresses (num_parameters); + for (int i=0; i < num_parameters; i++) { + switch (parameter_modes[i]) { + case PARAMETER_MODE_POSITION: + { + parameter_addresses[i] = memory_get(address+i); + break; + } + case PARAMETER_MODE_IMMEDIATE: + { + parameter_addresses[i] = address+i; + break; + } + } + } + return parameter_addresses; +} + +const int OPCODE_ADD = 1; +const int OPCODE_MULTIPLY = 2; +const int OPCODE_INPUT = 3; +const int OPCODE_OUTPUT = 4; +const int OPCODE_HALT = 99; + +int execute_operation(int opcode, vector parameter_addresses) { + switch (opcode) { + case OPCODE_ADD: + { + int term1 = memory_get(parameter_addresses[0]); + int term2 = memory_get(parameter_addresses[1]); + int output_address = parameter_addresses[2]; + + int output = term1 + term2; + memory_set(output_address, output); + break; + } + case OPCODE_MULTIPLY: + { + int factor1 = memory_get(parameter_addresses[0]); + int factor2 = memory_get(parameter_addresses[1]); + int output_address = parameter_addresses[2]; + + int output = factor1 * factor2; + memory_set(output_address, output); + break; + } + case OPCODE_INPUT: + { + int output_address = parameter_addresses[0]; + int input; + cin >> input; + memory_set(output_address, input); + break; + } + case OPCODE_OUTPUT: + { + int input_address = parameter_addresses[0]; + int output = memory_get(input_address); + cout << output << endl; + break; + } + case OPCODE_HALT: + { + return -1; + } + } + return 0; +} + +int main() { + int code; + char comma; + while (cin >> code) { + memory.push_back(code); + if (cin.peek() == ',') + cin >> comma; + else + break; + } + memory_size = memory.size(); + + int address = 0; + while (address < memory_size) { + auto [opcode, parameter_modes] = extract_opcode_parameter_modes(address); + vector parameter_addresses = get_parameters(address+1, num_parameters_for_opcode[opcode], parameter_modes); + if (execute_operation(opcode, parameter_addresses) == -1) + break; + address += 1+num_parameters_for_opcode[opcode]; + } +} + diff --git a/nerarith-c++/day5/5b.cpp b/nerarith-c++/day5/5b.cpp new file mode 100644 index 0000000..582542c --- /dev/null +++ b/nerarith-c++/day5/5b.cpp @@ -0,0 +1,194 @@ +#include +#include "prettyprint.hpp" +using namespace std; + +const int MAX_NUM_PARAMETERS = 3; + +set known_opcodes = {1, 2, 3, 4, 5, 6, 7, 8, 99}; +map num_parameters_for_opcode = { + {1, 3}, + {2, 3}, + {3, 1}, + {4, 1}, + {5, 2}, + {6, 2}, + {7, 3}, + {8, 3}, + {99, 0} +}; +vector memory; +int memory_size; +int memory_get (int address) { + if (0 <= address && address < memory_size) + return memory[address]; + else { + cerr << "error: out of bounds with address " << address << endl; + return -1; + } +} +void memory_set (int address, int value) { + if (0 <= address && address < memory_size) + memory[address] = value; + else + cerr << "error: out of bounds with address " << address << endl; +} + +pair> extract_opcode_parameter_modes (int address) { + int combined = memory_get(address); + int opcode = combined % 100; + combined /= 100; + vector parameter_modes (3); + for (int i=0; i < MAX_NUM_PARAMETERS; i++) { + parameter_modes[i] = combined % 10; + combined /= 10; + } + return {opcode, parameter_modes}; +} + +const int PARAMETER_MODE_POSITION = 0; +const int PARAMETER_MODE_IMMEDIATE = 1; + +vector get_parameters (int address, int num_parameters, vector parameter_modes) { + vector parameter_addresses (num_parameters); + for (int i=0; i < num_parameters; i++) { + switch (parameter_modes[i]) { + case PARAMETER_MODE_POSITION: + { + parameter_addresses[i] = memory_get(address+i); + break; + } + case PARAMETER_MODE_IMMEDIATE: + { + parameter_addresses[i] = address+i; + break; + } + } + } + return parameter_addresses; +} + +const int OPCODE_ADD = 1; +const int OPCODE_MULTIPLY = 2; +const int OPCODE_INPUT = 3; +const int OPCODE_OUTPUT = 4; +const int OPCODE_JUMP_IF_TRUE = 5; +const int OPCODE_JUMP_IF_FALSE = 6; +const int OPCODE_LESS_THAN = 7; +const int OPCODE_EQUALS = 8; +const int OPCODE_HALT = 99; + +pair execute_operation(int opcode, vector parameter_addresses) { + bool halt = false; + int new_address = -1; + switch (opcode) { + case OPCODE_ADD: + { + int term1 = memory_get(parameter_addresses[0]); + int term2 = memory_get(parameter_addresses[1]); + int output_address = parameter_addresses[2]; + + int output = term1 + term2; + memory_set(output_address, output); + break; + } + case OPCODE_MULTIPLY: + { + int factor1 = memory_get(parameter_addresses[0]); + int factor2 = memory_get(parameter_addresses[1]); + int output_address = parameter_addresses[2]; + + int output = factor1 * factor2; + memory_set(output_address, output); + break; + } + case OPCODE_INPUT: + { + int output_address = parameter_addresses[0]; + int input; + cin >> input; + memory_set(output_address, input); + break; + } + case OPCODE_OUTPUT: + { + int input_address = parameter_addresses[0]; + int output = memory_get(input_address); + cout << output << endl; + break; + } + case OPCODE_JUMP_IF_TRUE: + { + int condition = memory_get(parameter_addresses[0]); + if (condition != 0) + new_address = memory_get(parameter_addresses[1]); + break; + } + case OPCODE_JUMP_IF_FALSE: + { + int condition = memory_get(parameter_addresses[0]); + if (condition == 0) + new_address = memory_get(parameter_addresses[1]); + break; + } + case OPCODE_LESS_THAN: + { + int number1 = memory_get(parameter_addresses[0]); + int number2 = memory_get(parameter_addresses[1]); + int output_address = parameter_addresses[2]; + int result; + if (number1 < number2) + result = 1; + else + result = 0; + memory_set(output_address, result); + break; + } + case OPCODE_EQUALS: + { + int number1 = memory_get(parameter_addresses[0]); + int number2 = memory_get(parameter_addresses[1]); + int output_address = parameter_addresses[2]; + int result; + if (number1 == number2) + result = 1; + else + result = 0; + memory_set(output_address, result); + break; + } + case OPCODE_HALT: + { + halt = true; + break; + } + } + return {halt, new_address}; +} + +int main() { + int code; + char comma; + while (cin >> code) { + memory.push_back(code); + if (cin.peek() == ',') + cin >> comma; + else + break; + } + memory_size = memory.size(); + + int address = 0; + while (address < memory_size) { + auto [opcode, parameter_modes] = extract_opcode_parameter_modes(address); + vector parameter_addresses = get_parameters(address+1, num_parameters_for_opcode[opcode], parameter_modes); + + auto [halt, new_address] = execute_operation(opcode, parameter_addresses); + if (halt) + break; + + if (new_address != -1) + address = new_address; + else + address += 1+num_parameters_for_opcode[opcode]; + } +} diff --git a/nerarith-c++/day5/input b/nerarith-c++/day5/input new file mode 100644 index 0000000..e0e0700 --- /dev/null +++ b/nerarith-c++/day5/input @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1101,48,82,225,102,59,84,224,1001,224,-944,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1101,92,58,224,101,-150,224,224,4,224,102,8,223,223,1001,224,3,224,1,224,223,223,1102,10,89,224,101,-890,224,224,4,224,1002,223,8,223,1001,224,5,224,1,224,223,223,1101,29,16,225,101,23,110,224,1001,224,-95,224,4,224,102,8,223,223,1001,224,3,224,1,223,224,223,1102,75,72,225,1102,51,8,225,1102,26,16,225,1102,8,49,225,1001,122,64,224,1001,224,-113,224,4,224,102,8,223,223,1001,224,3,224,1,224,223,223,1102,55,72,225,1002,174,28,224,101,-896,224,224,4,224,1002,223,8,223,101,4,224,224,1,224,223,223,1102,57,32,225,2,113,117,224,101,-1326,224,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,1,148,13,224,101,-120,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,8,677,226,224,102,2,223,223,1006,224,329,101,1,223,223,107,677,677,224,1002,223,2,223,1006,224,344,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,359,101,1,223,223,107,226,226,224,102,2,223,223,1005,224,374,1001,223,1,223,1108,677,226,224,1002,223,2,223,1006,224,389,101,1,223,223,107,677,226,224,102,2,223,223,1006,224,404,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,419,1001,223,1,223,108,677,677,224,102,2,223,223,1005,224,434,1001,223,1,223,1008,677,226,224,1002,223,2,223,1006,224,449,1001,223,1,223,7,226,677,224,1002,223,2,223,1006,224,464,1001,223,1,223,1007,677,677,224,102,2,223,223,1005,224,479,1001,223,1,223,1007,226,226,224,1002,223,2,223,1005,224,494,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,509,1001,223,1,223,1007,226,677,224,1002,223,2,223,1006,224,524,101,1,223,223,1107,677,677,224,102,2,223,223,1005,224,539,101,1,223,223,1107,677,226,224,102,2,223,223,1005,224,554,1001,223,1,223,108,677,226,224,1002,223,2,223,1006,224,569,1001,223,1,223,1108,226,677,224,1002,223,2,223,1006,224,584,101,1,223,223,8,677,677,224,1002,223,2,223,1006,224,599,1001,223,1,223,1008,226,226,224,102,2,223,223,1006,224,614,101,1,223,223,7,677,677,224,1002,223,2,223,1006,224,629,101,1,223,223,1008,677,677,224,102,2,223,223,1005,224,644,101,1,223,223,7,677,226,224,1002,223,2,223,1005,224,659,101,1,223,223,1108,226,226,224,102,2,223,223,1006,224,674,1001,223,1,223,4,223,99,226 diff --git a/nerarith-c++/day5/run_5a b/nerarith-c++/day5/run_5a new file mode 100755 index 0000000..3801ce1 --- /dev/null +++ b/nerarith-c++/day5/run_5a @@ -0,0 +1,2 @@ +g++ -std=c++17 5a.cpp -o 5a +(cat input && echo "1") | ./5a diff --git a/nerarith-c++/day5/run_5b b/nerarith-c++/day5/run_5b new file mode 100755 index 0000000..59bcc4c --- /dev/null +++ b/nerarith-c++/day5/run_5b @@ -0,0 +1,2 @@ +g++ -std=c++17 5b.cpp -o 5b +(cat input && echo "5") | ./5b