-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathq2.cpp
125 lines (94 loc) · 3.1 KB
/
q2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <cassert>
#include <fmt/format.h>
#include <fstream>
#include <iostream>
#include <numeric>
using std::literals::string_literals::operator""s;
// helpers...
template<typename T>
std::vector<T> vectorize(std::istream& is) {
std::vector<T> vec;
T str;
while(std::getline(is, str)){
vec.push_back(str);
}
return vec;
}
int to_int(char c) {
assert(isdigit(c,std::locale()));
return c - '0';
}
// the rest...
enum class Colour {N, RED, GREEN, BLUE};
struct RGB_Count {
int red, green, blue;
};
void update_rgb(RGB_Count& rgb, Colour colour, int total) {
switch (colour) {
case Colour::RED: rgb.red = std::max(rgb.red, total); break;
case Colour::GREEN: rgb.green = std::max(rgb.green, total); break;
case Colour::BLUE: rgb.blue = std::max(rgb.blue, total); break;
default: break;
}
}
void reset(int& total, int& multi) {
total = 0; multi = 1;
}
// line parser ...
RGB_Count calc_max_of_each_colour(const std::string& line) {
RGB_Count rgb {0, 0, 0};
Colour current_colour = Colour::N;
int total = 0, multi = 1;
for (size_t i = line.length() - 1; i != std::numeric_limits<size_t>::max(); --i) { // i == std::numeric_limits<size_t>::max() when underflow.
const char current = line[i];
if (current == ':') break;
if ("0123456789rgb"s.find(current) == std::string::npos) continue;
if (isdigit(current)) {
total += to_int(current) * multi;
multi *= 10;
}
else if (total != 0) {
update_rgb(rgb, current_colour, total);
reset(total, multi);
}
switch (current) {
case 'r': current_colour = Colour::RED; break;
case 'g': current_colour = Colour::GREEN; break;
case 'b': current_colour = Colour::BLUE; break;
default: break;
}
}
update_rgb(rgb, current_colour, total);
return rgb;
}
bool is_valid(const RGB_Count& hand, const RGB_Count max) {
return max.red >= hand.red
&& max.green >= hand.green
&& max.blue >= hand.blue;
}
int main() {
std::ifstream data("../data.txt");
if (!data.is_open()) {
throw std::runtime_error("Unable to open file");
}
std::vector<std::string> lines = vectorize<std::string>(data);
const int part_1 = [&](){
const RGB_Count no_of_cubes {12, 13, 14};
int sum_of_indices = 0;
for (size_t i = 0; i < lines.size(); ++i) {
const RGB_Count min_hand = calc_max_of_each_colour(lines[i]);
sum_of_indices += is_valid(min_hand, no_of_cubes) ? static_cast<int>(i + 1) : 0;
}
return sum_of_indices;
}();
const int part_2 = [&](){
return std::accumulate(cbegin(lines), cend(lines), 0, [&](int acc, const std::string& line){
const RGB_Count min_hand = calc_max_of_each_colour(line);
const int power = min_hand.red * min_hand.green * min_hand.blue;
return acc + power;
});
}();
fmt::print("Part 1: {}\n", part_1);
fmt::print("Part 2: {}\n", part_2);
return 0;
}