#pragma once #include #include #include #include #include #include #include template struct powerset final { static_assert(std::is_integral_v, ""); using size_type = size_type_; static_assert(M > 0, ""); static_assert(M < sizeof(size_type[8]), ""); static_assert((std::is_unsigned_v) || M < sizeof(size_type)*8 - 1, ""); using N = std::integral_constant; static_assert((N::value & (N::value + 1)) == 0, ""); using set_type = std::vector; using sets_type = std::array; using element_type = t; using element_count = std::integral_constant; using self_type = powerset; operator const sets_type&() const { return sets_; } operator sets_type&() { return sets_; } const sets_type& sets() const { return sets_; } sets_type& sets() { return sets_; } set_type& operator[](unsigned k) { return sets_[k]; } const set_type& operator[](unsigned k) const { return sets_[k]; } const set_type& elements() const { return elements_; } set_type& elements() { return elements_; } template operator QString() const { QString str; unsigned k = 0; for (const auto& set : sets_) { str.append(QStringLiteral("#%1: ").arg(++k)); for (const auto& x : set) str.append(QStringLiteral("%1 ").arg(x)); str.append('\n'); } return str.mid(0, str.size() - 1); } powerset() {} private: sets_type sets_; set_type elements_; }; template inline auto make_powerset(const t& arg, const xs&... args) { using cnt = std::integral_constant; using p = powerset; using len = typename p::element_count; using vec = typename p::set_type; using size_type = typename p::size_type; p ret; vec v; v.reserve(len()); const typename p::set_type ts {{arg, static_cast(args)...}}; ret.elements() = std::vector(std::begin(ts), std::end(ts)); // no nullary set for (size_type i = 0; i < len(); i++) { v.clear(); size_type k = 1; for (const t& x : ts) { if ((i+1) & k) v.push_back(std::move(x)); k <<= 1; } ret[i] = vec(std::begin(v), std::end(v)); ret[i].shrink_to_fit(); } return ret; }