#include #include #include #include #include #include #include #include #include using namespace std; struct Entry { Entry(long destination, long source, long amount) // NOLINT : destination_(destination) , source_(source) , amount_(amount) { } [[nodiscard]] bool in_range(long value) const { return source_ <= value && value < (source_ + amount_); } [[nodiscard]] long get_destination(long value) const { auto delta = value - source_; return destination_ + delta; } long destination_; long source_; long amount_; }; vector read_file(string_view filename) { fstream input{ filename }; vector data; for ( string line; getline(input, line); ) { data.emplace_back(line); } return data; } vector split(const string& line, char sep) { vector parts{}; stringstream input{ line }; for ( string part; getline(input, part, sep); ) { parts.emplace_back(part); } return parts; } void part1() { auto lines = read_file("data/day05.txt"); auto read_ints = [](const string& line) { stringstream iss{ line }; return vector{ istream_iterator{ iss }, istream_iterator{} }; }; auto seeds = read_ints(lines[0].substr(6)); map category_mapping{}; map> range_mapping{}; // read blocks for ( size_t idx = 1; idx < lines.size(); ) { ++idx; // skip empty line auto description = lines[idx++]; description.erase(description.find(' ')); auto parts = split(description, '-'); category_mapping[parts[0]] = parts[2]; vector mapping{}; for ( ; idx < lines.size() && !lines[idx].empty(); ++idx ) { auto values = read_ints(lines[idx]); auto destination = values[0]; auto source = values[1]; auto amount = values[2]; mapping.emplace_back(destination, source, amount); } range_mapping[parts[0]] = mapping; } auto min_value = numeric_limits::max(); for ( auto seed: seeds ) { for ( string category{ "seed" }; !category.empty(); category = category_mapping[category] ) { const auto& ranges = range_mapping[category]; for (const auto& range: ranges) { if (range.in_range(seed)) { seed = range.get_destination(seed); break; } } } min_value = min(min_value, seed); } cout << min_value << endl; } void part2() { auto lines = read_file("data/day05-sample1.txt"); auto read_ints = [](const string& line) { stringstream iss{ line }; return vector{ istream_iterator{ iss }, istream_iterator{} }; }; auto seeds = read_ints(lines[0].substr(6)); map category_mapping{}; map> range_mapping{}; // read blocks for ( size_t idx = 1; idx < lines.size(); ) { ++idx; // skip empty line auto description = lines[idx++]; description.erase(description.find(' ')); auto parts = split(description, '-'); category_mapping[parts[0]] = parts[2]; vector mapping{}; for ( ; idx < lines.size() && !lines[idx].empty(); ++idx ) { auto values = read_ints(lines[idx]); auto destination = values[0]; auto source = values[1]; auto amount = values[2]; mapping.emplace_back(destination, source, amount); } range_mapping[parts[0]] = mapping; } // brute force -- slow, but works auto min_value = numeric_limits::max(); for ( size_t idx = 0; idx != seeds.size(); idx += 2 ) { for ( auto start = seeds[idx]; start != seeds[idx] + seeds[idx+1]; ++start ) { auto seed = start; for ( string category{ "seed" }; !category.empty(); category = category_mapping[category] ) { const auto& ranges = range_mapping[category]; for (const auto& range: ranges) { if (range.in_range(seed)) { seed = range.get_destination(seed); break; } } } min_value = min(min_value, seed); } } cout << min_value << endl; } int main() { part1(); part2(); }