aboutsummaryrefslogtreecommitdiff
path: root/src/day19.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/day19.cpp')
-rw-r--r--src/day19.cpp173
1 files changed, 129 insertions, 44 deletions
diff --git a/src/day19.cpp b/src/day19.cpp
index 3dbae22..c991d6d 100644
--- a/src/day19.cpp
+++ b/src/day19.cpp
@@ -1,4 +1,5 @@
1#include <fstream> 1#include <fstream>
2#include <functional>
2#include <iostream> 3#include <iostream>
3#include <map> 4#include <map>
4#include <regex> 5#include <regex>
@@ -41,83 +42,167 @@ part1()
41 const auto rules_string = split(input[0], "\n"); 42 const auto rules_string = split(input[0], "\n");
42 const auto parts = split(input[1], "\n"); 43 const auto parts = split(input[1], "\n");
43 44
44 const regex rules_pattern{ R"((.*)\{(.*),(.*)\})" };
45 const regex sub_rules_pattern{ R"((.)(.)(\d*):(.*))" };
46
47 map<string, tuple<vector<tuple<string, string, long, string>>, string>> rules; 45 map<string, tuple<vector<tuple<string, string, long, string>>, string>> rules;
48 46
49 for ( const auto& rule: rules_string ) { 47 for ( const auto& rule: rules_string ) {
48 static const regex rules_pattern{ R"((.*)\{(.*),(.*)\})" };
49
50 smatch smatch; 50 smatch smatch;
51 if ( regex_search(rule, smatch, rules_pattern) ) { 51 if ( regex_search(rule, smatch, rules_pattern) ) {
52 string rule_name = smatch[1]; 52 string rule_name = smatch[1];
53 string default_dest = smatch[3]; 53 string default_dest = smatch[3];
54 54
55 vector<tuple<string, string, long, string>> foo; 55 vector<tuple<string, string, long, string>> sub_rules;
56 56
57 for ( const auto& sub_rule: split(smatch[2].str(), ",") ) { 57 for ( const auto& sub_rule: split(smatch[2].str(), ",") ) {
58 static const regex sub_rules_pattern{ R"((.)(.)(\d*):(.*))" };
59
58 std::smatch smatch2; 60 std::smatch smatch2;
59 if ( regex_search(sub_rule, smatch2, sub_rules_pattern) ) { 61 if ( regex_search(sub_rule, smatch2, sub_rules_pattern) ) {
60 foo.emplace_back(smatch2[1], smatch2[2], stol(smatch2[3]), smatch2[4]); 62 sub_rules.emplace_back(smatch2[1], smatch2[2], stol(smatch2[3]), smatch2[4]);
61 } 63 }
62 } 64 }
63 65
64 rules[rule_name] = make_tuple(foo, default_dest); 66 rules[rule_name] = make_tuple(sub_rules, default_dest);
65 } 67 }
66 } 68 }
67 69
68 long sum = 0; 70 long sum = 0;
69 const regex parts_pattern{ R"(\{x=(\d*),m=(\d*),a=(\d*),s=(\d*)\})" };
70 for ( const auto& part: parts ) { 71 for ( const auto& part: parts ) {
72 static const regex parts_pattern{ R"(\{x=(\d*),m=(\d*),a=(\d*),s=(\d*)\})" };
73
71 smatch smatch; 74 smatch smatch;
72 if ( regex_search(part, smatch, parts_pattern) ) { 75 if ( !regex_search(part, smatch, parts_pattern) ) {
73 const auto xval = stol(smatch[1]); 76 continue;
74 const auto mval = stol(smatch[2]); 77 }
75 const auto aval = stol(smatch[3]);
76 const auto sval = stol(smatch[4]);
77 78
78 string rule = "in"; 79 map<string, long> values = {
79 while ( rule != "A" && rule != "R" ) { 80 { "x", stol(smatch[1]) },
80 auto sub_rules = get<0>(rules[rule]); 81 { "m", stol(smatch[2]) },
81 auto next_rule = get<1>(rules[rule]); 82 { "a", stol(smatch[3]) },
83 { "s", stol(smatch[4]) },
84 };
82 85
83 for ( auto sub_rule: sub_rules ) { 86 string rule = "in";
84 const auto field = get<0>(sub_rule); 87 while ( rule != "A" && rule != "R" ) {
85 const auto cmp = get<1>(sub_rule); 88 auto [sub_rules, next_rule] = rules[rule];
86 const auto value = get<2>(sub_rule);
87 89
88 if ( field == "x" && ((cmp == ">" && xval > value) || (cmp == "<" && xval < value)) ) { 90 for ( const auto& sub_rule: sub_rules ) {
89 next_rule = get<3>(sub_rule); 91 const auto [field, cmp, value, dest] = sub_rule;
90 break;
91 }
92 if ( field == "m" && ((cmp == ">" && mval > value) || (cmp == "<" && mval < value)) ) {
93 next_rule = get<3>(sub_rule);
94 break;
95 }
96 if ( field == "a" && ((cmp == ">" && aval > value) || (cmp == "<" && aval < value)) ) {
97 next_rule = get<3>(sub_rule);
98 break;
99 }
100 if ( field == "s" && ((cmp == ">" && sval > value) || (cmp == "<" && sval < value)) ) {
101 next_rule = get<3>(sub_rule);
102 break;
103 }
104 }
105 92
106 rule = next_rule; 93 if ( values.contains(field) && ((cmp == ">" && values[field] > value) || (cmp == "<" && values[field] < value)) ) {
107 } 94 next_rule = dest;
108 if (rule == "A") { 95 break;
109 sum += xval; 96 }
110 sum += mval;
111 sum += aval;
112 sum += sval;
113 } 97 }
98
99 rule = next_rule;
100 }
101
102 if ( rule == "A" ) {
103 sum += values["x"];
104 sum += values["m"];
105 sum += values["a"];
106 sum += values["s"];
114 } 107 }
115 } 108 }
116 cout << sum << endl; 109 cout << sum << endl;
117} 110}
118 111
112void
113part2()
114{
115 const auto input = split(read_file("data/day19.txt"), "\n\n");
116 const auto rules_string = split(input[0], "\n");
117
118 const regex rules_pattern{ R"((.*)\{(.*),(.*)\})" };
119 const regex sub_rules_pattern{ R"((.)(.)(\d*):(.*))" };
120
121 map<string, tuple<vector<tuple<string, string, long, string>>, string>> rules;
122
123 for ( const auto& rule: rules_string ) {
124 smatch smatch;
125 if ( regex_search(rule, smatch, rules_pattern) ) {
126 string rule_name = smatch[1];
127 string default_dest = smatch[3];
128
129 vector<tuple<string, string, long, string>> sub_rules;
130
131 for ( const auto& sub_rule: split(smatch[2].str(), ",") ) {
132 std::smatch smatch2;
133 if ( regex_search(sub_rule, smatch2, sub_rules_pattern) ) {
134 sub_rules.emplace_back(smatch2[1], smatch2[2], stol(smatch2[3]), smatch2[4]);
135 }
136 }
137
138 rules[rule_name] = make_tuple(sub_rules, default_dest);
139 }
140 }
141
142 function<long(map<string, tuple<long, long>>, string)> count = [&](map<string, tuple<long, long>> ranges, string name) -> long {
143 if ( name == "R" ) {
144 return 0;
145 }
146
147 if ( name == "A" ) {
148 long result = 1;
149 for ( const auto& range: ranges ) {
150 const auto [lo, hi] = range.second;
151 result *= hi - lo + 1;
152 }
153 return result;
154 }
155
156 const auto [sub_rules, fallback] = rules[name];
157
158 long result = 0;
159
160 bool run_trough = true;
161 for ( const auto& [key, cmp, value, target]: sub_rules ) {
162 const auto [lo, hi] = ranges[key];
163 pair<long, long> T; // NOLINT
164 pair<long, long> F; // NOLINT
165 if ( cmp == "<" ) {
166 T = { lo, min(value - 1, hi) };
167 F = { max(value, lo), hi };
168 }
169 else {
170 T = { max(value + 1, lo), hi };
171 F = { lo, min(value, hi) };
172 }
173 if ( T.first <= T.second ) {
174 auto copy = ranges;
175 copy[key] = T;
176 result += count(copy, target);
177 }
178 if ( F.first <= F.second ) {
179 ranges[key] = F;
180 }
181 else {
182 run_trough = false;
183 break;
184 }
185 }
186 if ( run_trough ) {
187 result += count(ranges, fallback);
188 }
189
190 return result;
191 };
192
193 cout << count({
194 { "x", { 1, 4000 } },
195 { "m", { 1, 4000 } },
196 { "a", { 1, 4000 } },
197 { "s", { 1, 4000 } },
198 },
199 "in")
200 << endl;
201}
202
119int 203int
120main() 204main()
121{ 205{
122 part1(); 206 part1();
207 part2();
123} 208}