diff options
Diffstat (limited to 'src/day19.cpp')
| -rw-r--r-- | src/day19.cpp | 173 |
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 | ||
| 112 | void | ||
| 113 | part2() | ||
| 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 | |||
| 119 | int | 203 | int |
| 120 | main() | 204 | main() |
| 121 | { | 205 | { |
| 122 | part1(); | 206 | part1(); |
| 207 | part2(); | ||
| 123 | } | 208 | } |
