Add day 14 solution for part 1
parent
1ff5938495
commit
7611af1289
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue