aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/day05.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/day05.cpp b/src/day05.cpp
new file mode 100644
index 0000000..26b5c66
--- /dev/null
+++ b/src/day05.cpp
@@ -0,0 +1,186 @@
1#include <algorithm>
2#include <fstream>
3#include <iostream>
4#include <iterator>
5#include <map>
6#include <sstream>
7#include <string>
8#include <vector>
9using namespace std;
10
11struct Entry {
12 Entry(long destination, long source, long amount) // NOLINT
13 : destination_(destination)
14 , source_(source)
15 , amount_(amount)
16 {
17 }
18
19 [[nodiscard]] bool in_range(long value) const
20 {
21 return source_ <= value && value < (source_ + amount_);
22 }
23
24 [[nodiscard]] long get_destination(long value) const
25 {
26 auto delta = value - source_;
27 return destination_ + delta;
28 }
29
30 long destination_;
31 long source_;
32 long amount_;
33};
34
35vector<string>
36read_file(string_view filename)
37{
38 fstream input{ filename };
39 vector<string> data;
40
41 for ( string line; getline(input, line); ) {
42 data.emplace_back(line);
43 }
44
45 return data;
46}
47
48vector<string>
49split(const string& line, char sep)
50{
51 vector<string> parts{};
52 stringstream input{ line };
53
54 for ( string part; getline(input, part, sep); ) {
55 parts.emplace_back(part);
56 }
57
58 return parts;
59}
60
61void
62part1()
63{
64 auto lines = read_file("data/day05.txt");
65
66 auto read_ints = [](const string& line) {
67 stringstream iss{ line };
68 return vector<long>{ istream_iterator<long>{ iss }, istream_iterator<long>{} };
69 };
70
71 auto seeds = read_ints(lines[0].substr(6));
72
73 map<string, string> category_mapping{};
74 map<string, vector<Entry>> range_mapping{};
75
76 // read blocks
77 for ( size_t idx = 1; idx < lines.size(); ) {
78 ++idx; // skip empty line
79
80 auto description = lines[idx++];
81 description.erase(description.find(' '));
82 auto parts = split(description, '-');
83
84 category_mapping[parts[0]] = parts[2];
85
86 vector<Entry> mapping{};
87
88 for ( ; idx < lines.size() && !lines[idx].empty(); ++idx ) {
89 auto values = read_ints(lines[idx]);
90
91 auto destination = values[0];
92 auto source = values[1];
93 auto amount = values[2];
94
95 mapping.emplace_back(destination, source, amount);
96 }
97
98 range_mapping[parts[0]] = mapping;
99 }
100
101 vector<long> values{};
102 for ( auto seed: seeds ) {
103 for ( string category{ "seed" }; !category.empty(); category = category_mapping[category] ) {
104 const auto& ranges = range_mapping[category];
105
106 for (const auto& range: ranges) {
107 if (range.in_range(seed)) {
108 seed = range.get_destination(seed);
109 break;
110 }
111 }
112 }
113 values.emplace_back(seed);
114 }
115 cout << *min_element(values.begin(), values.end()) << endl;
116}
117
118void
119part2()
120{
121 auto lines = read_file("data/day05.txt");
122
123 auto read_ints = [](const string& line) {
124 stringstream iss{ line };
125 return vector<long>{ istream_iterator<long>{ iss }, istream_iterator<long>{} };
126 };
127
128 auto seeds = read_ints(lines[0].substr(6));
129
130 map<string, string> category_mapping{};
131 map<string, vector<Entry>> range_mapping{};
132
133 // read blocks
134 for ( size_t idx = 1; idx < lines.size(); ) {
135 ++idx; // skip empty line
136
137 auto description = lines[idx++];
138 description.erase(description.find(' '));
139 auto parts = split(description, '-');
140
141 category_mapping[parts[0]] = parts[2];
142
143 vector<Entry> mapping{};
144
145 for ( ; idx < lines.size() && !lines[idx].empty(); ++idx ) {
146 auto values = read_ints(lines[idx]);
147
148 auto destination = values[0];
149 auto source = values[1];
150 auto amount = values[2];
151
152 mapping.emplace_back(destination, source, amount);
153 }
154
155 range_mapping[parts[0]] = mapping;
156 }
157
158 vector<long> values{};
159 for ( size_t idx = 0; idx != seeds.size(); idx += 2 ) {
160 cout << "." << endl;
161 vector<long> min_so_far{};
162 for ( auto start = seeds[idx]; start != seeds[idx] + seeds[idx+1]; ++start ) {
163 auto seed = start;
164
165 for ( string category{ "seed" }; !category.empty(); category = category_mapping[category] ) {
166 const auto& ranges = range_mapping[category];
167
168 for (const auto& range: ranges) {
169 if (range.in_range(seed)) {
170 seed = range.get_destination(seed);
171 break;
172 }
173 }
174 }
175 min_so_far.emplace_back(seed);
176 }
177 values.push_back(*min_element(min_so_far.begin(), min_so_far.end()));
178 }
179 cout << *min_element(values.begin(), values.end()) << endl;
180}
181
182int
183main()
184{
185 part2();
186}