aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/2020/day4/aoc.cpp23
-rw-r--r--src/2020/day4/aoc.h109
2 files changed, 115 insertions, 17 deletions
diff --git a/src/2020/day4/aoc.cpp b/src/2020/day4/aoc.cpp
index 171f42e..cd8fb64 100644
--- a/src/2020/day4/aoc.cpp
+++ b/src/2020/day4/aoc.cpp
@@ -2,26 +2,29 @@
namespace aoc2020 {
-int day4(line_view file) {
+std::pair<int, int> day4(line_view file) {
const char* p1 = file.line;
const char* p2 = file.line + file.length;
const char* p = p1;
- int total{0};
+ int t0{0};
+ int t1{0};
+ bool b1{false};
+ bool b2{false};
while (p < p2) {
if (*p == '\n' && *(p + 1) == '\n') {
- passwort pass{p1, p};
+ passport pass{p1, p};
// std::cout << pass << std::endl;
- if (pass.is_valid()) {
- total++;
- }
+ pass.is_valid(&b1, &b2);
+ t0 += int(b1);
+ t1 += int(b2);
p1 = p + 2;
}
p++;
}
- if (passwort{p1, p}.is_valid()) {
- total++;
- }
- return total;
+ passport{p1, p}.is_valid(&b1, &b2);
+ t0 += int(b1);
+ t1 += int(b2);
+ return {t0, t1};
}
} // namespace aoc2020
diff --git a/src/2020/day4/aoc.h b/src/2020/day4/aoc.h
index a0b42b5..663fa1b 100644
--- a/src/2020/day4/aoc.h
+++ b/src/2020/day4/aoc.h
@@ -4,7 +4,7 @@
namespace aoc2020 {
-struct passwort {
+struct passport {
line_view byr;
line_view iyr;
line_view eyr;
@@ -14,19 +14,114 @@ struct passwort {
line_view pid;
line_view cid;
- friend std::ostream& operator<<(std::ostream& o, const passwort& p) {
+ friend std::ostream& operator<<(std::ostream& o, const passport& p) {
o << p.byr << " " << p.iyr << " " << p.eyr << " ";
o << p.hgt << " " << p.hcl << " " << p.ecl << " ";
o << p.pid << " " << p.cid << " ";
return o;
}
- bool is_valid() const noexcept {
- return byr.length > 0 && iyr.length > 0 && eyr.length > 0 && hgt.length > 0 && hcl.length > 0 && ecl.length > 0 &&
- pid.length > 0;
+ void get_number(const char** pp, int* d) {
+ const char* p = *pp;
+ while (*p >= '0' && *p <= '9') {
+ *d = *d * 10 + *p - '0';
+ p++;
+ }
+ *pp = p;
+ }
+
+ typedef bool (passport::*cf)(line_view);
+
+ template <int A, int B, int C>
+ bool chk1(line_view lv) {
+ int y{0};
+ const char* p = lv.line;
+ get_number(&p, &y);
+ return lv.length == A && y >= B && y <= C;
+ }
+
+ bool chk2(line_view lv) {
+ int d{0};
+ const char* p = lv.line;
+ get_number(&p, &d);
+ bool b1 = (*p == 'c' && *(p + 1) == 'm') && d >= 150 && d <= 193;
+ bool b2 = (*p == 'i' && *(p + 1) == 'n') && d >= 59 && d <= 76;
+ return b1 || b2;
+ }
+
+ bool chk3(line_view lv) {
+ static const char* cs[] = {"amb", "blu", "brn", "gry", "grn", "hzl", "oth"};
+ for (auto c : cs) {
+ if (lv == c) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <int A, char B, char C>
+ bool chk4(line_view lv) {
+ const char* p = lv.line;
+ for (int i = 0; i < A; i++) {
+ if (*(p + i) < B || *(p + i) > C) {
+ return false;
+ }
+ }
+ return lv.length == A;
+ }
+
+ bool chk5(line_view lv) {
+ const char* p = lv.line + 1;
+ auto is_az = [](char c) { return c >= 'a' && c <= 'z'; };
+ auto is_09 = [](char c) { return c >= '0' && c <= '9'; };
+ while (p < lv.line + lv.length) {
+ if (!is_az(*p) && !is_09(*p)) {
+ return false;
+ }
+ p++;
+ }
+ return *lv.line == '#' && lv.length == 7;
+ }
+
+ // byr (Birth Year) - four digits; at least 1920 and at most 2002.
+ // iyr (Issue Year) - four digits; at least 2010 and at most 2020.
+ // eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
+ // hgt (Height) - a number followed by either cm or in:
+ // If cm, the number must be at least 150 and at most 193.
+ // If in, the number must be at least 59 and at most 76.
+ // hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f.
+ // ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth.
+ // pid (Passport ID) - a nine-digit number, including leading zeroes.
+ // cid (Country ID) - ignored, missing or not.
+
+ void is_valid(bool* b1, bool* b2) {
+ *b1 = byr.length > 0 && iyr.length > 0 && eyr.length > 0 && hgt.length > 0 && hcl.length > 0 && ecl.length > 0 &&
+ pid.length > 0;
+
+ *b2 = false;
+ if (*b1) {
+ struct {
+ cf f;
+ line_view* field;
+ } checkers[] = {
+ {&passport::chk1<4, 1920, 2002>, &byr},
+ {&passport::chk1<4, 2010, 2020>, &iyr},
+ {&passport::chk1<4, 2020, 2030>, &eyr},
+ {&passport::chk2, &hgt},
+ {&passport::chk5, &hcl},
+ {&passport::chk3, &ecl},
+ {&passport::chk4<9, '0', '9'>, &pid},
+ };
+ for (auto c : checkers) {
+ if (!((this->*(c.f))(*c.field))) {
+ return;
+ }
+ }
+ *b2 = true;
+ }
}
- passwort(const char* p1, const char* p2) {
+ passport(const char* p1, const char* p2) {
struct {
line_view* field;
const char* label;
@@ -64,5 +159,5 @@ struct passwort {
}
};
-int day4(line_view);
+std::pair<int, int> day4(line_view);
} // namespace aoc2020