You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
3.4 KiB
88 lines
3.4 KiB
#include <iterator>
|
|
#include <sstream>
|
|
#include <unordered_set>
|
|
#include <unordered_map>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
|
|
#include "solutions.hpp"
|
|
|
|
using namespace std;
|
|
|
|
bool is_digit(char c) {
|
|
return isdigit((int) c);
|
|
}
|
|
|
|
bool is_hex_digit(char c) {
|
|
return isdigit((int) c) || (c >= 'a' && c <= 'f');
|
|
}
|
|
|
|
pair<string, string> solve4(istream& input) {
|
|
cerr << boolalpha;
|
|
stringstream current_passport{string()};
|
|
uint64_t part1 = 0, part2 = 0;
|
|
unordered_map<string, function<bool(string&)>> valid_funcs;
|
|
valid_funcs["byr"] = [](string &value) {
|
|
int int_value = stoi(value);
|
|
return value.length() == 4 && all_of(value.begin(), value.end(), is_digit) && int_value >= 1920 && int_value <= 2002;
|
|
};
|
|
valid_funcs["iyr"] = [](string &value) {
|
|
int int_value = stoi(value);
|
|
return value.length() == 4 && all_of(value.begin(), value.end(), is_digit) && int_value >= 2010 && int_value <= 2020;
|
|
};
|
|
valid_funcs["eyr"] = [](string &value) {
|
|
int int_value = stoi(value);
|
|
return value.length() == 4 && all_of(value.begin(), value.end(), is_digit) && int_value >= 2020 && int_value <= 2030;
|
|
};
|
|
valid_funcs["hgt"] = [](string &value) {
|
|
int int_value = stoi(value);
|
|
return (value.length() == to_string(int_value).length() + 2) && (
|
|
(value.ends_with("in") && int_value >= 59 && int_value <= 76) ||
|
|
(value.ends_with("cm") && int_value >= 150 && int_value <= 193)
|
|
);
|
|
};
|
|
valid_funcs["hcl"] = [](string &value) {
|
|
auto it = value.begin();
|
|
return value.length() == 7 && *it == '#' && all_of(next(it), value.end(), is_hex_digit);
|
|
};
|
|
valid_funcs["ecl"] = [](string &value) {
|
|
unordered_set<string> valid_eye_colors = { {
|
|
"amb"s, "blu"s, "brn"s, "gry"s, "grn"s, "hzl"s, "oth"s
|
|
} };
|
|
return valid_eye_colors.contains(value);
|
|
};
|
|
valid_funcs["pid"] = [](string &value) {
|
|
return value.length() == 9 && all_of(value.begin(), value.end(), is_digit);
|
|
};
|
|
|
|
for (string line; getline(input, line); ) {
|
|
if (!line.empty()) { // append to existing passport
|
|
if (!current_passport.eof()) {
|
|
current_passport << ' ';
|
|
}
|
|
current_passport << line;
|
|
}
|
|
if (line.empty() || input.peek() == EOF) { // no input; parse current passport
|
|
unordered_set<string> mandatory_fields = {
|
|
{ "byr"s, "iyr"s, "eyr"s, "hgt"s, "hcl"s, "ecl"s, "pid"s}
|
|
};
|
|
bool all_fields_valid = true;
|
|
for (string entry; getline(current_passport, entry, ' '); ) {
|
|
auto field_delim_pos = entry.find(':');
|
|
if (field_delim_pos != string::npos) {
|
|
string field_name = entry.substr(0, field_delim_pos);
|
|
string field_value = entry.substr(field_delim_pos+1);
|
|
mandatory_fields.erase(field_name);
|
|
if (valid_funcs.contains(field_name)) {
|
|
all_fields_valid = all_fields_valid && valid_funcs[field_name](field_value);
|
|
}
|
|
}
|
|
}
|
|
current_passport.clear();
|
|
part1 += (uint64_t) mandatory_fields.empty();
|
|
part2 += (uint64_t) (mandatory_fields.empty() && all_fields_valid);
|
|
}
|
|
}
|
|
return pair(to_string(part1), to_string(part2));
|
|
}
|