aboutsummaryrefslogtreecommitdiff
path: root/2024/src/day24-alt.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2024/src/day24-alt.cpp')
-rw-r--r--2024/src/day24-alt.cpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/2024/src/day24-alt.cpp b/2024/src/day24-alt.cpp
new file mode 100644
index 0000000..df6d333
--- /dev/null
+++ b/2024/src/day24-alt.cpp
@@ -0,0 +1,197 @@
1#include <array>
2#include <fstream>
3#include <iostream>
4#include <map>
5#include <set>
6#include <sstream>
7#include <string>
8#include <vector>
9using namespace std;
10
11vector<string>
12split(string_view line, string_view delimiter)
13{
14 size_t pos_start = 0;
15 size_t pos_end = 0;
16
17 vector<string> res;
18
19 while ( (pos_end = line.find(delimiter, pos_start)) != std::string::npos ) {
20 auto token = line.substr(pos_start, pos_end - pos_start);
21 pos_start = pos_end + delimiter.length();
22
23 res.emplace_back(token);
24 }
25
26 res.emplace_back(line.substr(pos_start));
27 return res;
28}
29
30template<typename Container>
31string
32join(const Container& container, const string& delimiter)
33{
34 ostringstream oss;
35 auto it = container.begin();
36 if ( it != container.end() ) {
37 oss << *it;
38 ++it;
39 }
40 while ( it != container.end() ) {
41 oss << delimiter << *it;
42 ++it;
43 }
44 return oss.str();
45}
46
47tuple<map<string, unsigned long>, map<string, tuple<string, string, string>>>
48read_file(string_view filename)
49{
50 fstream input{ filename };
51 const auto parts = split(string{ istreambuf_iterator<char>{ input }, {} }, "\n\n");
52
53 map<string, unsigned long> inputs;
54
55 // register => { reg1 operator reg2 }
56 map<string, tuple<string, string, string>> deps;
57
58 stringstream spart1{ parts[0] };
59 for ( string line; getline(spart1, line); ) {
60 const auto foo = split(line, ": ");
61 inputs[foo[0]] = stoul(foo[1]);
62 }
63
64 stringstream spart2{ parts[1] };
65 for ( string line; getline(spart2, line); ) {
66 const auto foo = split(line, " ");
67 deps[foo[4]] = { foo[0], foo[1], foo[2] };
68 }
69
70 return { inputs, deps };
71}
72
73void
74part1(const tuple<map<string, unsigned long>, map<string, tuple<string, string, string>>>& data)
75{
76 auto inputs = get<0>(data);
77 const auto& deps = get<1>(data);
78
79 function<unsigned long(const string&)> eval = [&](const string& input) -> unsigned long {
80 if ( inputs.contains(input) ) {
81 return inputs.at(input);
82 }
83
84 const auto& [lhs, op, rhs] = deps.at(input);
85
86 unsigned long value = 0;
87
88 if ( op == "XOR" ) {
89 value = eval(lhs) ^ eval(rhs);
90 }
91 else if ( op == "AND" ) {
92 value = eval(lhs) & eval(rhs);
93 }
94 else if ( op == "OR" ) {
95 value = eval(lhs) | eval(rhs);
96 }
97 else {
98 cerr << "Das darf nicht passieren! Input: " << input << endl;
99 }
100
101 inputs[input] = value;
102
103 return value;
104 };
105
106 unsigned long value = 0;
107 for ( const auto& [first, second]: deps ) {
108 if ( first.starts_with("z") ) {
109 if ( eval(first) != 0 ) {
110 auto bit = stoul(first.substr(1));
111 value |= 1UL << bit;
112 }
113 }
114 }
115 cout << value << endl;
116}
117
118void
119debug(const tuple<map<string, unsigned long>, map<string, tuple<string, string, string>>>& data)
120{
121 const auto& deps = get<1>(data);
122
123 function<void(const string&, size_t)> eval = [&](const string& input, size_t depth) {
124 if ( !deps.contains(input) ) {
125 return;
126 }
127
128 if ( depth == 3 ) {
129 return;
130 }
131
132 const auto& [lhs, op, rhs] = deps.at(input);
133
134 const string indent(depth * 2, ' ');
135
136 cout << indent << op << " (" << input << ")\n"
137 << indent << " - " << lhs << "\n"
138 << indent << " - " << rhs << endl;
139
140 eval(lhs, depth + 1);
141 eval(rhs, depth + 1);
142 };
143
144 eval("z02", 0);
145 eval("z16", 0);
146 eval("z17", 0);
147}
148
149void
150part2(const tuple<map<string, unsigned long>, map<string, tuple<string, string, string>>>& data)
151{
152 auto deps = get<1>(data);
153
154 set<string> wrong;
155 for ( const auto& [res, formula]: deps ) {
156 const auto& [op1, op, op2] = formula;
157
158 if ( res.starts_with('z') && op != "XOR" && res != "z45" ) {
159 wrong.insert(res);
160 }
161
162 static const set<char> starts{ 'x', 'y', 'z' };
163
164 if ( op == "XOR" && !starts.contains(res[0]) && !starts.contains(op1[0]) && !starts.contains(op2[0]) ) {
165 wrong.insert(res);
166 }
167
168 if ( op == "AND" && op1 != "x00" && op2 != "x00" ) {
169 for ( const auto& [subres, subformula]: deps ) {
170 const auto& [subop1, subop, subop2] = subformula;
171 if ( (res == subop1 || res == subop2) and subop != "OR" ) {
172 wrong.insert(res);
173 }
174 }
175 }
176
177 if ( op == "XOR" ) {
178 for ( const auto& [subres, subformula]: deps ) {
179 const auto& [subop1, subop, subop2] = subformula;
180 if ( (res == subop1 || res == subop2) and subop == "OR" ) {
181 wrong.insert(res);
182 }
183 }
184 }
185 }
186
187 cout << join(wrong, ",") << endl;
188}
189
190int
191main()
192{
193 const auto data = read_file("data/day24.txt");
194 // debug(data);
195 part1(data);
196 part2(data);
197}