Add day 14 solution for part 1

master
Nick Krichevsky 2020-12-14 01:08:45 -05:00
parent 1ff5938495
commit 7611af1289
2 changed files with 130 additions and 0 deletions

15
day14/Makefile Normal file
View File

@ -0,0 +1,15 @@
CC=g++
BIN_NAME=day14
CCFLAGS=-o $(BIN_NAME) -g -std=c++17
LDFLAGS=-lfolly
.PHONY: all, clean
all: $(BIN_NAME)
clean:
rm -f $(BIN_NAME)
$(BIN_NAME): day14.cpp
$(CC) $(CCFLAGS) $(LDFLAGS) day14.cpp

115
day14/day14.cpp Normal file
View File

@ -0,0 +1,115 @@
#include <folly/String.h>
#include <algorithm>
#include <cassert>
#include <charconv>
#include <fstream>
#include <iostream>
#include <map>
#include <numeric>
#include <regex>
#include <vector>
constexpr char IGNORE_CHAR = 'X';
constexpr auto MASK_PATTERN = R"(mask = ([X0-9]+))";
constexpr auto MEM_PATTERN = R"(mem\[(\d+)\] = (\d+))";
class InstructionBlock {
public:
InstructionBlock(std::string mask, std::vector<std::pair<int, int>> storeInstructions)
: mask(mask), storeInstructions(storeInstructions) {
}
// 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 res = num;
for (int i = 0; i < this->mask.size(); i++) {
char maskChar = this->mask.at(this->mask.size() - i - 1);
if (maskChar == IGNORE_CHAR) {
continue;
} else if (maskChar == '0') {
res &= ~(1LL << i);
} else if (maskChar == '1') {
res |= (1LL << i);
}
}
return res;
}
const std::vector<std::pair<int, int>> &getStoreInstructions() const {
return this->storeInstructions;
}
private:
std::string mask;
std::vector<std::pair<int, int>> storeInstructions;
};
std::vector<std::string> readInput(const std::string &filename) {
std::vector<std::string> input;
std::string line;
std::ifstream file(filename);
while (std::getline(file, line)) {
input.push_back(line);
}
return input;
}
std::vector<InstructionBlock> parseInput(const std::vector<std::string> &input) {
std::vector<InstructionBlock> blocks;
std::regex maskExpression(MASK_PATTERN);
std::regex memExpression(MEM_PATTERN);
std::string currentMask;
std::vector<std::pair<int, int>> currentStoreInstructions;
for (auto it = input.cbegin(); it != input.cend(); it++) {
auto line = *it;
std::smatch matches;
if (std::regex_match(line, matches, maskExpression)) {
// We don't want to emplace on the first mask we find
if (it != input.cbegin()) {
blocks.emplace_back(currentMask, currentStoreInstructions);
currentStoreInstructions.clear();
}
currentMask = matches[1];
} else if (std::regex_match(line, matches, memExpression)) {
int address = std::stoi(matches[1]);
int value = std::stoi(matches[2]);
currentStoreInstructions.emplace_back(address, value);
}
}
// Put in the last one we've found
blocks.emplace_back(currentMask, currentStoreInstructions);
return blocks;
}
long long part1(const std::vector<InstructionBlock> &instructions) {
std::unordered_map<int, long long> memory;
for (const InstructionBlock &instruction : instructions) {
for (const std::pair<int, int> &storeInstruction : instruction.getStoreInstructions()) {
auto maskedStorage = instruction.maskNumber(storeInstruction.second);
memory[storeInstruction.first] = maskedStorage;
}
}
return std::accumulate(
memory.cbegin(), memory.cend(), 0LL, [](long long total, std::pair<int, long long> memoryItem) {
return total + memoryItem.second;
});
}
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cerr << argv[0] << " <input_file>" << std::endl;
return 1;
}
auto input = readInput(argv[1]);
auto parsedInput = parseInput(input);
std::cout << part1(parsedInput) << std::endl;
}