Add solution for day 14 part 2
parent
7611af1289
commit
6270ea51ea
|
@ -8,6 +8,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
constexpr char IGNORE_CHAR = 'X';
|
constexpr char IGNORE_CHAR = 'X';
|
||||||
|
@ -21,22 +22,24 @@ class InstructionBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are dealing with a 36 bit numebr so we must use a long long to guarantee we can fit it
|
// We are dealing with a 36 bit numebr so we must use a long long to guarantee we can fit it
|
||||||
long long maskNumber(long long num) const {
|
long long maskValue(long long num) const {
|
||||||
long long res = num;
|
long long res = num;
|
||||||
for (int i = 0; i < this->mask.size(); i++) {
|
for (int i = 0; i < this->mask.size(); i++) {
|
||||||
char maskChar = this->mask.at(this->mask.size() - i - 1);
|
char maskChar = this->mask.at(this->mask.size() - i - 1);
|
||||||
if (maskChar == IGNORE_CHAR) {
|
if (maskChar == IGNORE_CHAR) {
|
||||||
continue;
|
continue;
|
||||||
} else if (maskChar == '0') {
|
} else {
|
||||||
res &= ~(1LL << i);
|
res = this->setBitAt(res, i, maskChar);
|
||||||
} else if (maskChar == '1') {
|
|
||||||
res |= (1LL << i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<long long> maskMemoryAddress(long long address) const {
|
||||||
|
return this->recursivelyMaskAddresses(address);
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<int, int>> &getStoreInstructions() const {
|
const std::vector<std::pair<int, int>> &getStoreInstructions() const {
|
||||||
return this->storeInstructions;
|
return this->storeInstructions;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +47,40 @@ class InstructionBlock {
|
||||||
private:
|
private:
|
||||||
std::string mask;
|
std::string mask;
|
||||||
std::vector<std::pair<int, int>> storeInstructions;
|
std::vector<std::pair<int, int>> storeInstructions;
|
||||||
|
|
||||||
|
long long setBitAt(long long value, int position, char bit) const {
|
||||||
|
auto res = value;
|
||||||
|
if (bit == '0') {
|
||||||
|
res &= ~(1LL << position);
|
||||||
|
} else if (bit == '1') {
|
||||||
|
res |= (1LL << position);
|
||||||
|
} else {
|
||||||
|
throw std::invalid_argument("bit must be zero or one");
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<long long> recursivelyMaskAddresses(long long address, int startIdx = 0) const {
|
||||||
|
std::vector<long long> results;
|
||||||
|
long long res = address;
|
||||||
|
for (int i = startIdx; i < this->mask.size(); i++) {
|
||||||
|
char maskChar = this->mask.at(this->mask.size() - i - 1);
|
||||||
|
if (maskChar == IGNORE_CHAR) {
|
||||||
|
auto masked0 = this->setBitAt(res, i, '0');
|
||||||
|
auto masked1 = this->setBitAt(res, i, '1');
|
||||||
|
auto results0 = this->recursivelyMaskAddresses(masked0, i + 1);
|
||||||
|
auto results1 = this->recursivelyMaskAddresses(masked1, i + 1);
|
||||||
|
results.insert(results.end(), results0.begin(), results0.end());
|
||||||
|
results.insert(results.end(), results1.begin(), results1.end());
|
||||||
|
} else if (maskChar == '1') {
|
||||||
|
res = this->setBitAt(res, i, maskChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.push_back(res);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::string> readInput(const std::string &filename) {
|
std::vector<std::string> readInput(const std::string &filename) {
|
||||||
|
@ -91,8 +128,24 @@ long long part1(const std::vector<InstructionBlock> &instructions) {
|
||||||
std::unordered_map<int, long long> memory;
|
std::unordered_map<int, long long> memory;
|
||||||
for (const InstructionBlock &instruction : instructions) {
|
for (const InstructionBlock &instruction : instructions) {
|
||||||
for (const std::pair<int, int> &storeInstruction : instruction.getStoreInstructions()) {
|
for (const std::pair<int, int> &storeInstruction : instruction.getStoreInstructions()) {
|
||||||
auto maskedStorage = instruction.maskNumber(storeInstruction.second);
|
auto maskedValue = instruction.maskValue(storeInstruction.second);
|
||||||
memory[storeInstruction.first] = maskedStorage;
|
memory[storeInstruction.first] = maskedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::accumulate(
|
||||||
|
memory.cbegin(), memory.cend(), 0LL, [](long long total, std::pair<int, long long> memoryItem) {
|
||||||
|
return total + memoryItem.second;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
long long part2(const std::vector<InstructionBlock> &instructions) {
|
||||||
|
std::unordered_map<long long, long long> memory;
|
||||||
|
for (const InstructionBlock &instruction : instructions) {
|
||||||
|
for (const std::pair<int, int> &storeInstruction : instruction.getStoreInstructions()) {
|
||||||
|
for (const auto maskedAddress : instruction.maskMemoryAddress(storeInstruction.first)) {
|
||||||
|
memory[maskedAddress] = storeInstruction.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,4 +165,5 @@ int main(int argc, char *argv[]) {
|
||||||
auto parsedInput = parseInput(input);
|
auto parsedInput = parseInput(input);
|
||||||
|
|
||||||
std::cout << part1(parsedInput) << std::endl;
|
std::cout << part1(parsedInput) << std::endl;
|
||||||
|
std::cout << part2(parsedInput) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue