#include #include #include #include #include #include #include #include "common.hh" namespace param { using namespace ::args; ArgumentParser parser { "converter: bmap -> fmap" }; HelpFlag help { parser, "help", "display this menu", {'h', "help"}, }; ValueFlag fnum { parser, "64", "number of feature kinds", {"fnum"}, 64, }; ValueFlag seed { parser, "0", "random seed to randomize selection of combination (0=no randomize)", {"seed"}, 0, }; } // namespace param static bool NextCombination(auto begin, auto end) noexcept { auto first = std::find(begin, end, true); if (first == end) { return false; } if (!NextCombination(first+1, end)) { if (first+1 >= end || *(first+1)) { return false; } const auto n = std::count(first+2, end, true); std::fill(first+2 , first+2+n, true); std::fill(first+2+n, end , false); *first = false; *(first+1) = true; } return true; } static uint32_t XorShift(uint32_t* v) noexcept { *v ^= *v << 13; *v ^= *v >> 17; *v ^= *v << 5; return *v; } static void Exec() { const auto bmap = ReadMatrix(std::cin); const auto fnum = args::get(param::fnum); for (uint32_t t = 0; t < bmap.size(); ++t) { const auto& blocks = bmap[t]; const auto bnum = static_cast(blocks.size()); Enforce(fnum < pow(bnum, 2), "number of blocks is too less"); // calc skip vector std::vector skip(fnum); uint32_t nCr = 1; for (uint32_t f = 0, r = 1; f < fnum; ++r) { nCr *= bnum - (r-1); nCr /= r; f += nCr; if (f <= fnum || 0 == args::get(param::seed)) { const auto n = fnum - (f-nCr); auto begin = skip.begin() + f-nCr; std::fill(begin, begin+n, 1); } else { uint32_t seed = args::get(param::seed); uint64_t sum = 0; for (uint32_t i = f-nCr; i < fnum; ++i) { skip[i] = XorShift(&seed); sum += skip[i]; } sum += XorShift(&seed); const auto coe = nCr*1. / sum; for (uint32_t i = f-nCr; i < fnum; ++i) { skip[i] = std::max(uint32_t {1}, static_cast(skip[i] * coe)); } } } std::vector C(bnum); uint32_t r = 0; for (uint32_t f = 0; f < fnum; ++f) { for (uint32_t s = 0; s < skip[f]; ++s) { if (!NextCombination(C.begin(), C.end())) { ++r; assert(r <= bnum); std::fill(C.begin(), C.begin()+r, 1); std::fill(C.begin()+r, C.end(), 0); s = 0; // s will be 1 on next iteration } } auto itr = C.begin(); for (uint32_t i = 0; i < r; ++i, ++itr) { itr = std::find(itr, C.end(), true); if (itr >= C.end()) { for (const auto& b : C) std::cout << !!b << ','; std::cout << std::endl; assert(false); } const auto idx = std::distance(C.begin(), itr); std::cout << blocks[idx] << ' '; } std::cout << '\n'; } std::cout << "----\n"; } } int main(int argc, char** argv) try { param::parser.ParseCLI(argc, argv); Exec(); return EXIT_SUCCESS; } catch (const args::Help&) { std::cout << param::parser << std::endl; return EXIT_SUCCESS; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; }