#include #include #include #include #include #include #include #include #include #include #include #include "conv/common.hh" namespace param { using namespace ::args; ArgumentParser parser { "converter: feature code probability matrix -> feature code" }; HelpFlag help { parser, "help", "display this menu", {'h', "help"}, }; enum StepAlgo { kIncrement, }; const std::unordered_map kStepAlgo = { {"inc", kIncrement}, }; MapFlag algo { parser, "inc", "step algorithm (inc)", {"algorithm", "algo"}, kStepAlgo, }; Group inc { parser, "increment algorithm parameters" }; ValueFlag inc_min { inc, "1", "max stride of increment algorithm", {"inc-min"}, 1, }; ValueFlag inc_max { inc, "1", "max stride of increment algorithm", {"inc-max"}, 1, }; Flag output_prob { parser, "output-prob", "prints path probability at last", {"output-prob", "prob"}, }; } // namespace param static auto GenerateLegalStepMap(size_t dur, size_t n) { const auto inc_max = args::get(param::inc_max); const auto inc_min = args::get(param::inc_min); Enforce(0 <= inc_min && inc_min <= inc_max, "invalid increment stride"); std::vector> ret; ret.resize(dur*n); auto legals = &ret[0]; for (size_t t = 0; t < dur; ++t) { for (size_t i = 0; i < n; ++i) { switch (args::get(param::algo)) { case param::kIncrement: legals->reserve(inc_max-inc_min+1); for (uint32_t j = inc_min; j <= inc_max; ++j) { legals->push_back(static_cast((i+j)%n)); } break; } ++legals; } } return ret; } static void Exec() { const auto cprobs = ReadMatrix(std::cin); Enforce(cprobs.size() > 0 && cprobs[0].size() > 0, "empty matrix"); const auto dur = cprobs.size(); const auto n = cprobs[0].size(); const auto lmap = GenerateLegalStepMap(dur, n); struct Step { double prob = -1; size_t from = 0; }; std::vector steps((dur+1)*n); for (size_t i = 0; i < n; ++i) { steps[i].prob = cprobs[0][i]; } for (size_t t = 1; t < dur; ++t) { Enforce(cprobs[t].size() == n, "ill-formed matrix"); for (size_t i = 0; i < n; ++i) { const auto& cur = steps[(t-1)*n + i]; for (auto j : lmap[t*n+i]) { auto& next = steps[t*n + j]; const auto sum = cur.prob + cprobs[t][j]; if (next.prob < sum) { next.prob = sum; next.from = i; } } } } double max_prob = -1; size_t max_idx = 0; for (size_t i = 0; i < n; ++i) { const auto& step = steps[(dur-1)*n + i]; if (max_prob < step.prob) { max_prob = step.prob; max_idx = i; } } std::vector path = {max_idx}; path.reserve(dur); for (size_t t = dur-1; t > 0; --t) { path.push_back(steps[t*n + path.back()].from); } for (auto itr = path.rbegin(); itr < path.rend(); ++itr) { std::cout << *itr << '\n'; } if (param::output_prob) { std::cout << max_prob/static_cast(path.size())*100 << "%" << std::endl; } } 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; }