aboutsummaryrefslogtreecommitdiff
path: root/2024/src/day13-z3.cpp
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2024-12-14 14:28:00 +0100
committerThomas Schmucker <ts@its1.de>2024-12-14 14:28:00 +0100
commitdf89ce46eebb355acf353600b148de52641f060c (patch)
tree4e1969bccb250df713c4bbfb47e883aa28041b0e /2024/src/day13-z3.cpp
parent5a17843904394e73f5ae7001dd5f22b7491f6bb9 (diff)
downloadadvent-of-code-df89ce46eebb355acf353600b148de52641f060c.tar.gz
advent-of-code-df89ce46eebb355acf353600b148de52641f060c.tar.bz2
advent-of-code-df89ce46eebb355acf353600b148de52641f060c.zip
aoc 2024, day 13, lösung mit z3
Diffstat (limited to '2024/src/day13-z3.cpp')
-rw-r--r--2024/src/day13-z3.cpp110
1 files changed, 110 insertions, 0 deletions
diff --git a/2024/src/day13-z3.cpp b/2024/src/day13-z3.cpp
new file mode 100644
index 0000000..4f2755a
--- /dev/null
+++ b/2024/src/day13-z3.cpp
@@ -0,0 +1,110 @@
1#include <array>
2#include <fstream>
3#include <iostream>
4#include <iterator>
5#include <numeric>
6#include <regex>
7#include <vector>
8#include <z3++.h>
9using namespace std;
10
11vector<string>
12split(string_view line, string_view delimiter)
13{
14 string::size_type pos_start = 0;
15 string::size_type pos_end = 0;
16
17 vector<string> res;
18 while ( (pos_end = line.find(delimiter, pos_start)) != string::npos ) {
19 res.emplace_back(line.substr(pos_start, pos_end - pos_start));
20
21 pos_start = pos_end + delimiter.length();
22 }
23 if ( pos_start != line.size() ) {
24 res.emplace_back(line.substr(pos_start));
25 }
26 return res;
27}
28
29vector<array<long, 6>>
30read_file(string_view filename)
31{
32 static const regex pattern{ R"((\d+).*\+(\d+).*\+(\d+).*\+(\d+).*=(\d+).*=(\d+))" };
33
34 fstream input{ filename };
35 string content{ istreambuf_iterator<char>{ input }, {} };
36
37 auto parts = split(content, "\n\n");
38
39 vector<array<long, 6>> data;
40 for ( auto part: parts ) {
41 part.erase(std::remove(part.begin(), part.end(), '\n'), part.cend());
42
43 smatch matches;
44 if ( regex_search(part, matches, pattern) ) {
45 data.push_back({ stoi(matches[1]),
46 stoi(matches[2]),
47 stoi(matches[3]),
48 stoi(matches[4]),
49 stoi(matches[5]),
50 stoi(matches[6]) });
51 }
52 }
53
54 return data;
55}
56
57long
58test_z3(const array<long, 6>& machine, long offset)
59{
60 auto config = z3::config();
61 auto context = z3::context(config);
62 auto solver = z3::solver(context);
63
64 const auto i = context.int_const("i");
65 const auto j = context.int_const("j");
66
67 solver.add(i > 0);
68 solver.add(j > 0);
69
70 const auto button_a_x = context.int_val(machine[0]);
71 const auto button_a_y = context.int_val(machine[1]);
72 const auto button_b_x = context.int_val(machine[2]);
73 const auto button_b_y = context.int_val(machine[3]);
74 const auto price_x = context.int_val(machine[4] + offset);
75 const auto price_y = context.int_val(machine[5] + offset);
76
77 solver.add(i * button_a_x + j * button_b_x == price_x);
78 solver.add(i * button_a_y + j * button_b_y == price_y);
79
80 if ( solver.check() == z3::sat ) {
81 auto model = solver.get_model();
82 return model.eval(i).as_int64() * 3 + model.eval(j).as_int64();
83 }
84
85 return 0;
86}
87
88void
89part1(const vector<array<long, 6>>& machines)
90{
91 cout << accumulate(machines.begin(), machines.end(), 0L, [](auto init, const auto& machine) {
92 return init + test_z3(machine, 0);
93 }) << endl;
94}
95
96void
97part2(const vector<array<long, 6>>& machines)
98{
99 cout << accumulate(machines.begin(), machines.end(), 0L, [](auto init, const auto& machine) {
100 return init + test_z3(machine, 10000000000000);
101 }) << endl;
102}
103
104int
105main()
106{
107 auto data = read_file("data/day13.txt");
108 part1(data);
109 part2(data);
110}