Day 18: Lavaduct Lagoon
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
C++
No scala today
#include #include #include <map> #include #include #include #include #include #include #include #include struct HorizontalEdge { boost::icl::discrete_interval x; long y; }; long area(std::vector he) { if(he.empty()) return 0; boost::icl::interval_set intervals; std::ranges::sort(he, std::less{}, &HorizontalEdge::y); long area{}; long y = he.front().y; for(auto const& e : he) { area += intervals.size() * (e.y - std::exchange(y, e.y)); if(intervals.find(e.x) != intervals.end()) intervals.erase(e.x); else intervals.add(e.x); } return area; } struct Instruction { long l; int d; std::string color; }; enum Dir { R=0, U=1, L=2, D=3 }; std::unordered_map char_to_dir = {{'R', R}, {'U', U}, {'L', L}, {'D', D}}; auto transcode(std::vector const& is) { return flux::from(std::move(is)).map([](Instruction in) { long v = std::stoul(in.color.substr(0, 5), nullptr, 16); return Instruction{.l = v, .d = (4 - (in.color.at(5) - '0')) % 4, .color=""}; }).to>(); } std::vector read(std::string path) { std::ifstream in(std::move(path)); return flux::getlines(in).map([](std::string const& s) { Instruction i; char dir; if(auto r = scn::scan(s, "{} {} (#{:6})", dir, i.l, i.color)) { i.d = char_to_dir[dir]; return i; } else { throw std::runtime_error{r.error().msg()}; } }).to>(); } auto turns(std::vector is) { if(is.empty()) throw std::runtime_error{"Too few elements"}; is.push_back(is.front()); return flux::from(std::move(is)).pairwise_map([](auto const& lhs, auto const& rhs) { return (rhs.d - lhs.d + 4) % 4 == 1; }); } std::vector toEdges(std::vector is, bool left) { std::vector res; long x{}, y{}; auto t = turns(is).to>(); // some magic required to turn the ### path into its outer edge // (which is the actual object we want to compute the area for) for(size_t j = 0; j < is.size(); ++j) { auto const& i = is.at(j); bool s1 = t.at((j + t.size() - 1) % t.size()) == left; bool s2 = t.at(j) == left; long sign = (i.d == U || i.d == L) ? -1 : 1; long old_x = x; if(i.d == R || i.d == L) { x += i.l * sign; auto [l, r] = old_x < x ? std::tuple{old_x + !s1, x + s2} : std::tuple{x + !s2, old_x + s1}; res.push_back(HorizontalEdge{.x = {l, r, boost::icl::interval_bounds::right_open()}, .y = y}); } else { y += (i.l + s1 + s2 - 1) * sign; } } return res; } long solve(std::vector is) { auto tn = turns(is).sum() - ssize(is); return area(toEdges(std::move(is), tn > 0)); } int main(int argc, char* argv[]) { auto instructions = read(argc > 1 ? argv[1] : "../task1.txt"); auto start = std::chrono::steady_clock::now(); fmt::print("task1={}\ntask2={}\n", solve(instructions), solve(transcode(std::move(instructions)))); fmt::print("took {}\n", std::chrono::steady_clock::now() - start); } ```</map>
looks like some broken XSS protection is killing the includes, can’t really fix that