2023 Day 5
This commit is contained in:
102
2023/puzzle-05-01.cc
Normal file
102
2023/puzzle-05-01.cc
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using UInt = std::uint64_t;
|
||||
using NumVec = std::vector<UInt>;
|
||||
|
||||
auto operator<<(std::ostream& os, NumVec const& vec) -> std::ostream&
|
||||
{
|
||||
for (auto const num : vec) { os << ' ' << num; }
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
void read_nums(It it, std::string_view const nums)
|
||||
{
|
||||
char const* pos{nums.data()};
|
||||
while (pos - nums.data() < nums.size()) {
|
||||
char* next_pos{nullptr};
|
||||
*it++ = std::strtoull(pos, &next_pos, 10);
|
||||
pos = next_pos;
|
||||
}
|
||||
}
|
||||
|
||||
struct MapEntry
|
||||
{
|
||||
explicit MapEntry(NumVec const& vec)
|
||||
: dest_(vec[0]), source_(vec[1]), length_(vec[2])
|
||||
{
|
||||
assert(vec.size() == 3);
|
||||
}
|
||||
|
||||
UInt dest_;
|
||||
UInt source_;
|
||||
UInt length_;
|
||||
};
|
||||
|
||||
struct ThingyMap
|
||||
{
|
||||
void add(std::string_view line)
|
||||
{
|
||||
NumVec vec;
|
||||
read_nums(std::back_inserter(vec), line);
|
||||
assert(vec.size() == 3);
|
||||
entries_.emplace_back(vec);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto transform(UInt const in) const -> UInt
|
||||
{
|
||||
for (auto const [dest, source, length] : entries_) {
|
||||
if (in < source) { continue; }
|
||||
if (in >= source + length) { continue; }
|
||||
return dest + (in - source);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
std::vector<MapEntry> entries_;
|
||||
};
|
||||
|
||||
auto main() -> int try {
|
||||
std::string line;
|
||||
NumVec seeds{};
|
||||
std::getline(std::cin, line);
|
||||
|
||||
// Read the seeds.
|
||||
assert(line.substr(0, 6) == "seeds:");
|
||||
read_nums(std::back_inserter(seeds), line.substr(6));
|
||||
std::cout << "Seeds:" << seeds << '\n';
|
||||
|
||||
// Skip whitespace
|
||||
std::getline(std::cin, line);
|
||||
|
||||
while (std::getline(std::cin, line)) {
|
||||
std::cout << line << ":";
|
||||
ThingyMap map;
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (line.empty()) { break; }
|
||||
map.add(line);
|
||||
}
|
||||
NumVec transformed;
|
||||
|
||||
std::transform(seeds.begin(), seeds.end(), std::back_inserter(transformed),
|
||||
[&map](UInt in) { return map.transform(in); });
|
||||
std::cout << transformed << '\n';
|
||||
seeds = transformed;
|
||||
}
|
||||
|
||||
std::cout << "Minimum: " << *std::ranges::min_element(seeds.begin(), seeds.end()) << '\n';;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Uncaught exception.\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
150
2023/puzzle-05-02.cc
Normal file
150
2023/puzzle-05-02.cc
Normal file
@@ -0,0 +1,150 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using UInt = std::uint64_t;
|
||||
using NumVec = std::vector<UInt>;
|
||||
using Range = std::pair<UInt, UInt>;
|
||||
using RangeVec = std::vector<Range>;
|
||||
|
||||
auto operator<<(std::ostream& os, RangeVec const& ranges) -> std::ostream&
|
||||
{
|
||||
for (auto [start, length] : ranges) {
|
||||
os << " [" << start << '+' << length << ']';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
void read_nums(It it, std::string_view const nums)
|
||||
{
|
||||
char const* pos{nums.data()};
|
||||
while (pos - nums.data() < nums.size()) {
|
||||
char* next_pos{nullptr};
|
||||
*it++ = std::strtoull(pos, &next_pos, 10);
|
||||
pos = next_pos;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
void read_ranges(It it, std::string_view const nums)
|
||||
{
|
||||
char const* pos{nums.data()};
|
||||
while (pos - nums.data() < nums.size()) {
|
||||
char* next_pos{nullptr};
|
||||
auto start = std::strtoull(pos, &next_pos, 10);
|
||||
pos = next_pos;
|
||||
auto length = std::strtoull(pos, &next_pos, 10);
|
||||
pos = next_pos;
|
||||
*it++ = std::make_pair(start, length);
|
||||
}
|
||||
}
|
||||
|
||||
struct MapEntry
|
||||
{
|
||||
explicit MapEntry(NumVec const& vec)
|
||||
: dest_(vec[0]), source_(vec[1]), length_(vec[2])
|
||||
{
|
||||
assert(vec.size() == 3);
|
||||
}
|
||||
|
||||
UInt dest_;
|
||||
UInt source_;
|
||||
UInt length_;
|
||||
};
|
||||
|
||||
struct ThingyMap
|
||||
{
|
||||
void add(std::string_view const line)
|
||||
{
|
||||
NumVec vec;
|
||||
read_nums(std::back_inserter(vec), line);
|
||||
assert(vec.size() == 3);
|
||||
entries_.emplace_back(vec);
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
void transform(It it, UInt const range_start, UInt const range_length) const
|
||||
{
|
||||
/* Look for a start range that starts inside a map entry. */
|
||||
for (auto const [dest, source, length] : entries_) {
|
||||
if (range_start < source) { continue; }
|
||||
if (range_start >= source + length) { continue; }
|
||||
auto const offset = range_start - source;
|
||||
auto const new_length = std::min(range_length, length - offset);
|
||||
assert(new_length != 0);
|
||||
*it++ = std::make_pair(dest + offset, new_length);
|
||||
if (new_length != range_length) {
|
||||
transform(it, range_start + new_length, range_length - new_length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now look for an end that ends inside a map entry. */
|
||||
for (auto const [dest, source, length] : entries_) {
|
||||
auto const range_end = range_start + range_length;
|
||||
if (range_end <= source) { continue; }
|
||||
if (range_end > source + length) { continue; }
|
||||
assert(source > range_start);
|
||||
auto const new_length = source - range_start;
|
||||
assert(new_length != 0);
|
||||
*it++ = std::make_pair(range_start, new_length);
|
||||
if (range_length != new_length) {
|
||||
transform(it, range_start + new_length, range_length - new_length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
*it++ = std::make_pair(range_start, range_length);
|
||||
}
|
||||
|
||||
std::vector<MapEntry> entries_;
|
||||
};
|
||||
|
||||
auto main() -> int try {
|
||||
std::string line;
|
||||
RangeVec seeds{};
|
||||
std::getline(std::cin, line);
|
||||
|
||||
// Read the seeds.
|
||||
assert(line.substr(0, 6) == "seeds:");
|
||||
read_ranges(std::back_inserter(seeds), line.substr(6));
|
||||
std::cout << "Seeds:" << seeds << '\n';
|
||||
|
||||
// Skip whitespace
|
||||
std::getline(std::cin, line);
|
||||
|
||||
while (std::getline(std::cin, line)) {
|
||||
std::cout << line << ":";
|
||||
ThingyMap map;
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (line.empty()) { break; }
|
||||
map.add(line);
|
||||
}
|
||||
RangeVec transformed;
|
||||
|
||||
for (auto [start, length] : seeds) {
|
||||
map.transform(std::back_inserter(transformed), start, length);
|
||||
}
|
||||
std::cout << transformed << '\n';
|
||||
seeds = transformed;
|
||||
}
|
||||
|
||||
std::cout << "Minimum: " << std::ranges::min_element(seeds.begin(), seeds.end(),
|
||||
[](Range const& left, Range const& right) {
|
||||
return left.first < right.first;
|
||||
})->first << '\n';
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Uncaught exception.\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
Reference in New Issue
Block a user