aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2025-12-10 21:01:19 +0100
committerThomas Schmucker <ts@its1.de>2025-12-10 21:01:19 +0100
commite8bdb4f2ddb1a5137ecbfbe528f40c1cd253df17 (patch)
tree8513d89b359ba594929dbb3a09399e74efa7d58b
parent3f7af92f6ddb727312530783f10d67cbd8525548 (diff)
downloadadvent-of-code-e8bdb4f2ddb1a5137ecbfbe528f40c1cd253df17.tar.gz
advent-of-code-e8bdb4f2ddb1a5137ecbfbe528f40c1cd253df17.tar.bz2
advent-of-code-e8bdb4f2ddb1a5137ecbfbe528f40c1cd253df17.zip
aoc 2025, day 10, part 2
-rw-r--r--2025/src/day10p2.cpp159
-rw-r--r--makefile3
2 files changed, 162 insertions, 0 deletions
diff --git a/2025/src/day10p2.cpp b/2025/src/day10p2.cpp
new file mode 100644
index 0000000..a011bd3
--- /dev/null
+++ b/2025/src/day10p2.cpp
@@ -0,0 +1,159 @@
1#include <algorithm>
2#include <filesystem>
3#include <fstream>
4#include <iostream>
5#include <sstream>
6#include <string>
7#include <vector>
8#include <z3++.h>
9
10using namespace std;
11
12namespace {
13
14struct Machine {
15 Machine(const vector<vector<unsigned long>>& buttons, const vector<unsigned long>& joltages)
16 : buttons_{ buttons }
17 , joltages_{ joltages }
18 {
19 }
20
21 vector<vector<unsigned long>> buttons_;
22 vector<unsigned long> joltages_;
23};
24
25vector<string>
26split(const string& str, const string& delims)
27{
28 vector<string> result;
29
30 size_t start = str.find_first_not_of(delims);
31 while ( start != string::npos ) {
32 size_t end = str.find_first_of(delims, start);
33
34 if ( end == string::npos ) {
35 // letzter Teil
36 result.push_back(str.substr(start));
37 break;
38 }
39
40 result.push_back(str.substr(start, end - start));
41
42 start = str.find_first_not_of(delims, end);
43 }
44
45 return result;
46}
47
48vector<unsigned long>
49split(const string& str)
50{
51 stringstream strm{ str };
52 vector<unsigned long> values;
53
54 for ( string part; getline(strm, part, ','); ) {
55 values.emplace_back(stoul(part));
56 }
57
58 return values;
59}
60
61vector<Machine>
62read_file(const filesystem::path& filename)
63{
64 ifstream file{ filename };
65
66 vector<Machine> machines;
67
68 for ( string line; getline(file, line); ) {
69 const auto parts = split(line, "[] (){}");
70
71 vector<vector<unsigned long>> buttons;
72 for ( size_t i = 1; i < parts.size() - 1; ++i ) {
73 buttons.emplace_back(split(parts[i]));
74 }
75
76 const auto joltages = split(parts[parts.size() - 1]);
77
78 machines.emplace_back(buttons, joltages);
79 }
80
81 return machines;
82}
83
84unsigned long
85simulate(const Machine& machine)
86{
87 using namespace z3;
88
89 context ctx;
90 optimize opt(ctx);
91
92 const size_t num_buttons = machine.buttons_.size();
93 const size_t num_counters = machine.joltages_.size();
94
95 // Z3-Variablen: Anzahl der Button-Presses
96 vector<expr> vars;
97 vars.reserve(num_buttons);
98
99 for ( size_t i = 0; i != num_buttons; ++i ) {
100 expr var = ctx.int_const(("x_" + to_string(i)).c_str());
101 opt.add(var >= 0); // natürliche Zahlen
102 vars.emplace_back(var);
103 }
104
105 // Joltage-Constraints: Für jeden Counter i
106 for ( size_t i = 0; i != num_counters; ++i ) {
107 expr sum = ctx.int_val(0);
108
109 for ( size_t j = 0; j != num_buttons; ++j ) {
110 // Prüfen: affectet Button j den Counter i?
111 const auto& btn = machine.buttons_[j];
112 if ( ranges::find(btn, i) != btn.end() ) {
113 sum = sum + vars[j];
114 }
115 }
116
117 opt.add(sum == (int) machine.joltages_[i]);
118 }
119
120 // Zielfunktion: Minimale Gesamtzahl der Presses
121 expr total = ctx.int_val(0);
122 for ( size_t i = 0; i != num_buttons; ++i ) {
123 total = total + vars[i];
124 }
125
126 opt.minimize(total);
127
128 // Solve
129 if ( opt.check() != sat ) {
130 throw runtime_error("Machine has no valid solution!");
131 }
132
133 auto model = opt.get_model();
134
135 unsigned long presses = 0;
136 for ( size_t j = 0; j < num_buttons; ++j ) {
137 presses += model.eval(vars[j]).get_numeral_uint();
138 }
139 return presses;
140}
141
142void
143part2(const vector<Machine>& machines)
144{
145 unsigned long count = 0;
146 for ( const auto& machine: machines ) {
147 count += simulate(machine);
148 }
149 cout << "Part 2: " << count << '\n';
150}
151
152} // namespace
153
154int
155main()
156{
157 auto machines = read_file("data/day10.txt");
158 part2(machines);
159}
diff --git a/makefile b/makefile
index 634c220..536ac76 100644
--- a/makefile
+++ b/makefile
@@ -62,6 +62,9 @@ all: $(patsubst 2015/src/%.cpp,2015/bin/%,$(wildcard 2015/src/*.cpp)) \
622025/bin/%: 2025/src/%.cpp | 2025/bin 622025/bin/%: 2025/src/%.cpp | 2025/bin
63 c++ $(CPPFLAGS) $^ -o $@ 63 c++ $(CPPFLAGS) $^ -o $@
64 64
652025/bin/day10p2: 2025/src/day10p2.cpp | 2025/bin
66 c++ $(CPPFLAGS) -Wno-sign-conversion $^ -lz3 -o $@
67
65clean: 68clean:
66 rm -rf 2015/bin 2016/bin 2017/bin 2020/bin 2022/bin 2023/bin 2024/bin 2025/bin 69 rm -rf 2015/bin 2016/bin 2017/bin 2020/bin 2022/bin 2023/bin 2024/bin 2025/bin
67 70