128 lines
2.8 KiB
C++
128 lines
2.8 KiB
C++
|
#include <algorithm>
|
||
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <vector>
|
||
|
#include <deque>
|
||
|
|
||
|
uint64_t getIllegalScore(char closer) {
|
||
|
switch (closer) {
|
||
|
case ')':
|
||
|
return 3;
|
||
|
case ']':
|
||
|
return 57;
|
||
|
case '}':
|
||
|
return 1197;
|
||
|
case '>':
|
||
|
return 25137;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint64_t getCompletionScore(char closer) {
|
||
|
switch (closer) {
|
||
|
case ')':
|
||
|
return 1;
|
||
|
case ']':
|
||
|
return 2;
|
||
|
case '}':
|
||
|
return 3;
|
||
|
case '>':
|
||
|
return 4;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
std::vector<std::string> getLines(const std::string &file_name) {
|
||
|
std::vector<std::string> lines;
|
||
|
|
||
|
std::ifstream file(file_name);
|
||
|
std::string str;
|
||
|
while (std::getline(file, str)) {
|
||
|
lines.push_back(str);
|
||
|
}
|
||
|
return lines;
|
||
|
}
|
||
|
|
||
|
char getCloser(char opener) {
|
||
|
switch (opener) {
|
||
|
case '(':
|
||
|
return ')';
|
||
|
case '[':
|
||
|
return ']';
|
||
|
case '{':
|
||
|
return '}';
|
||
|
case '<':
|
||
|
return '>';
|
||
|
}
|
||
|
return '-';
|
||
|
}
|
||
|
|
||
|
bool isOpener(char opener) {
|
||
|
return opener == '(' || opener == '[' || opener == '{' || opener == '<';
|
||
|
}
|
||
|
|
||
|
uint64_t getCompleteScore(std::deque<char> &expected) {
|
||
|
uint64_t score = 0;
|
||
|
while (expected.size() != 0) {
|
||
|
score *= 5;
|
||
|
score += getCompletionScore(expected.back());
|
||
|
expected.pop_back();
|
||
|
}
|
||
|
return score;
|
||
|
}
|
||
|
|
||
|
uint64_t getScore(const std::string &line, bool corrupted) {
|
||
|
std::deque<char> expected{};
|
||
|
for (auto &c : line) {
|
||
|
if (isOpener(c)) {
|
||
|
expected.push_back(getCloser(c));
|
||
|
} else if (expected.back() == c) {
|
||
|
expected.pop_back();
|
||
|
} else {
|
||
|
if (corrupted) {
|
||
|
return getIllegalScore(c);
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (corrupted) {
|
||
|
return 0;
|
||
|
}
|
||
|
return getCompleteScore(expected);
|
||
|
}
|
||
|
|
||
|
uint64_t part1(const std::vector<std::string> &lines) {
|
||
|
uint64_t score = 0;
|
||
|
for (const auto &line : lines) {
|
||
|
score += getScore(line, true);
|
||
|
}
|
||
|
return score;
|
||
|
}
|
||
|
|
||
|
uint64_t part2(const std::vector<std::string> &lines) {
|
||
|
std::vector<uint64_t> scores{};
|
||
|
for (const auto &line : lines) {
|
||
|
auto score = getScore(line, false);
|
||
|
if (score != 0) {
|
||
|
scores.push_back(score);
|
||
|
}
|
||
|
}
|
||
|
std::sort(scores.begin(), scores.end());
|
||
|
return scores[(scores.size() - 1) / 2];
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
if (argc < 2) {
|
||
|
std::cerr << "You must provide input file!" << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
auto lines = getLines(argv[1]);
|
||
|
std::cout << "There total syntax error score is \033[91;1m" << part1(lines)
|
||
|
<< "\033[0m." << std::endl;
|
||
|
std::cout << "The middle completion score is \033[91;1m" << part2(lines)
|
||
|
<< "\033[0m." << std::endl;
|
||
|
return 0;
|
||
|
}
|