aboutsummaryrefslogtreecommitdiff
path: root/src/day19.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/day19.cpp')
-rw-r--r--src/day19.cpp183
1 files changed, 0 insertions, 183 deletions
diff --git a/src/day19.cpp b/src/day19.cpp
deleted file mode 100644
index a1d4eab..0000000
--- a/src/day19.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
1#include <fstream>
2#include <functional>
3#include <iostream>
4#include <map>
5#include <regex>
6#include <string>
7#include <vector>
8using namespace std;
9
10string
11read_file(string_view filename)
12{
13 fstream input{ filename };
14 return { istreambuf_iterator<char>{ input }, istreambuf_iterator<char>{} };
15}
16
17vector<string>
18split(string_view line, string_view delimiter)
19{
20 size_t pos_start = 0;
21 size_t pos_end = 0;
22
23 vector<string> res;
24
25 while ( (pos_end = line.find(delimiter, pos_start)) != string::npos ) {
26 auto token = line.substr(pos_start, pos_end - pos_start);
27 pos_start = pos_end + delimiter.length();
28
29 res.emplace_back(token);
30 }
31
32 if ( pos_start != line.size() ) {
33 res.emplace_back(line.substr(pos_start));
34 }
35 return res;
36}
37
38void
39part1(map<string, tuple<vector<tuple<string, string, long, string>>, string>> rules, const vector<string>& parts)
40{
41 long sum = 0;
42 for ( const auto& part: parts ) {
43 static const regex parts_pattern{ R"(\{x=(\d*),m=(\d*),a=(\d*),s=(\d*)\})" };
44
45 smatch smatch;
46 if ( !regex_search(part, smatch, parts_pattern) ) {
47 continue;
48 }
49
50 map<string, long> values = {
51 { "x", stol(smatch[1]) },
52 { "m", stol(smatch[2]) },
53 { "a", stol(smatch[3]) },
54 { "s", stol(smatch[4]) },
55 };
56
57 string rule = "in";
58 while ( rule != "A" && rule != "R" ) {
59 auto [sub_rules, next_rule] = rules[rule];
60
61 for ( const auto& sub_rule: sub_rules ) {
62 const auto [field, cmp, value, dest] = sub_rule;
63
64 if ( values.contains(field) && ((cmp == ">" && values[field] > value) || (cmp == "<" && values[field] < value)) ) {
65 next_rule = dest;
66 break;
67 }
68 }
69
70 rule = next_rule;
71 }
72
73 if ( rule == "A" ) {
74 sum += values["x"];
75 sum += values["m"];
76 sum += values["a"];
77 sum += values["s"];
78 }
79 }
80 cout << sum << endl;
81}
82
83void
84part2(map<string, tuple<vector<tuple<string, string, long, string>>, string>> rules)
85{
86 function<long(map<string, tuple<long, long>>, string)> count = [&](map<string, tuple<long, long>> ranges, const string& name) -> long {
87 if ( name == "R" ) {
88 return 0;
89 }
90
91 if ( name == "A" ) {
92 long result = 1;
93 for ( const auto& range: ranges ) {
94 const auto [lo, hi] = range.second;
95 result *= hi - lo + 1;
96 }
97 return result;
98 }
99
100 const auto [sub_rules, fallback] = rules[name];
101
102 long result = 0;
103
104 bool run_trough = true;
105 for ( const auto& [key, cmp, value, target]: sub_rules ) {
106 const auto [lo, hi] = ranges[key];
107 pair<long, long> T; // NOLINT
108 pair<long, long> F; // NOLINT
109 if ( cmp == "<" ) {
110 T = { lo, min(value - 1, hi) };
111 F = { max(value, lo), hi };
112 }
113 else {
114 T = { max(value + 1, lo), hi };
115 F = { lo, min(value, hi) };
116 }
117 if ( T.first <= T.second ) {
118 auto copy = ranges;
119 copy[key] = T;
120 result += count(copy, target);
121 }
122 if ( F.first <= F.second ) {
123 ranges[key] = F;
124 }
125 else {
126 run_trough = false;
127 break;
128 }
129 }
130 if ( run_trough ) {
131 result += count(ranges, fallback);
132 }
133
134 return result;
135 };
136
137 cout << count({
138 { "x", { 1, 4000 } },
139 { "m", { 1, 4000 } },
140 { "a", { 1, 4000 } },
141 { "s", { 1, 4000 } },
142 },
143 "in")
144 << endl;
145}
146
147int
148main()
149{
150 const auto input = split(read_file("data/day19.txt"), "\n\n");
151 const auto rules_string = split(input[0], "\n");
152 const auto parts = split(input[1], "\n");
153
154 map<string, tuple<vector<tuple<string, string, long, string>>, string>> rules;
155
156 for ( const auto& rule: rules_string ) {
157 static const regex rules_pattern{ R"((.*)\{(.*),(.*)\})" };
158
159 smatch smatch;
160 if ( !regex_search(rule, smatch, rules_pattern) ) {
161 continue;
162 }
163
164 string name = smatch[1];
165 string default_rule = smatch[3];
166
167 vector<tuple<string, string, long, string>> sub_rules;
168
169 for ( const auto& sub_rule: split(smatch[2].str(), ",") ) {
170 static const regex sub_rules_pattern{ R"((.)(.)(\d*):(.*))" };
171
172 std::smatch smatch2;
173 if ( regex_search(sub_rule, smatch2, sub_rules_pattern) ) {
174 sub_rules.emplace_back(smatch2[1], smatch2[2], stol(smatch2[3]), smatch2[4]);
175 }
176 }
177
178 rules[name] = make_tuple(sub_rules, default_rule);
179 }
180
181 part1(rules, parts);
182 part2(rules);
183}