Day 8: Playground
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++
Both parts in 40 ms. As always, the real AoC with C++ is parsing the input, although having a number that changes in the puzzle messes up my test/ solution runners.
Uses Boost’s implementations of sets, since they’re just plain faster than the STL ones.
Code
#include <boost/log/trivial.hpp> #include <boost/unordered/unordered_flat_set.hpp> #include <filesystem> #include <fstream> #include <stdexcept> namespace { struct Point { int x, y, z; }; auto distance(const Point &a, const Point &b) { auto &[ax, ay, az] = a; auto &[bx, by, bz] = b; ssize_t dx = ax - bx; ssize_t dy = ay - by; ssize_t dz = az - bz; return size_t(dx * dx + dy * dy + dz * dz); } using PList = std::vector<Point>; using DMap = std::vector<std::pair<std::pair<size_t, size_t>, size_t>>; using DSet = boost::unordered::unordered_flat_set<size_t>; auto read() { auto rval = PList{}; auto ih = std::ifstream{"08.txt"}; auto line = std::string{}; while (std::getline(ih, line)) { auto c1 = line.find(','); auto c2 = line.find(',', c1 + 1); rval.emplace_back( std::stoi(line.substr(0, c1)), std::stoi(line.substr(c1 + 1, c2 - c1 - 1)), std::stoi(line.substr(c2 + 1)) ); } return rval; } auto dmap(const PList &t) { auto rval = DMap{}; for (auto a = size_t{}; a < t.size() - 1; ++a) for (auto b = a + 1; b < t.size(); ++b) rval.emplace_back(std::make_pair(a, b), distance(t.at(a), t.at(b))); return rval; } auto find(size_t c, std::vector<DSet> &sets) { for (auto i = sets.begin(); i != sets.end(); ++i) if (i->contains(c)) return i; throw std::runtime_error{"can't find"}; } auto part1(const PList &t, size_t count, const DMap &d) { auto circuits = std::vector<DSet>{}; for (auto i = size_t{}; i < t.size(); ++i) { auto c = DSet{t.size()}; c.insert(i); circuits.push_back(std::move(c)); } for (auto i = size_t{}; i < count; ++i) { auto a = d.at(i).first.first; auto b = d.at(i).first.second; auto ac = find(a, circuits); auto bc = find(b, circuits); if (ac == bc) continue; ac->insert(bc->begin(), bc->end()); circuits.erase(bc); } std::sort(circuits.begin(), circuits.end(), [](auto &a, auto &b) { return a.size() > b.size(); }); auto total = size_t{1}; for (auto i = size_t{}; i < 3; ++i) total *= circuits.at(i).size(); return total; } auto part2(const PList &t, const DMap &d) { auto circuits = std::vector<DSet>{}; for (auto i = size_t{}; i < t.size(); ++i) { auto c = DSet{t.size()}; c.insert(i); circuits.push_back(std::move(c)); } for (auto i = size_t{}; i < d.size(); ++i) { auto a = d.at(i).first.first; auto b = d.at(i).first.second; auto ac = find(a, circuits); auto bc = find(b, circuits); if (ac == bc) continue; ac->insert(bc->begin(), bc->end()); circuits.erase(bc); if (circuits.size() == 1) { return ssize_t(t.at(a).x) * ssize_t(t.at(b).x); } } throw std::runtime_error{"never joins?"}; } } // namespace auto main() -> int { auto t = read(); BOOST_LOG_TRIVIAL(info) << "Day 8: read " << t.size(); auto test = std::filesystem::current_path().filename().string() == std::string{"test"}; auto d = dmap(t); std::sort(d.begin(), d.end(), [](auto &a, auto &b) { return a.second < b.second; }); BOOST_LOG_TRIVIAL(info) << "1: " << part1(t, test ? 10 : 1000, d); BOOST_LOG_TRIVIAL(info) << "2: " << part2(t, d); }