#include <fstream>
#include <iostream>
#include <string>

#include <args.hxx>

#include "common.hh"


namespace param {
using namespace ::args;

ArgumentParser parser {
  "converter: alter-probability matrix -> feature probability matrix"
};
HelpFlag help {
  parser, "help", "display this menu", {'h', "help"},
};

ValueFlag<std::string> fmap {
  parser, "path", "feature map file path", {"fmap"},
};

}  // namespace param


static void Exec() {
  const auto aprobs = ReadMatrix<double>(std::cin);
  Enforce(aprobs.size() > 0 && aprobs[0].size() > 0, "empty matrix");

  std::ifstream fmap_st {args::get(param::fmap)};
  Enforce(!!fmap_st, "fmap path is invalid");
  const auto fmap = ReadTensor3<uint32_t>(fmap_st);
  Enforce(fmap.size() > 0 && fmap[0].size() > 0, "empty fmap");
  for (auto& fmap_t : fmap) {
    Enforce(fmap_t.size() == fmap[0].size(), "fmap is broken");
  }

  for (size_t t = 0; t < aprobs.size(); ++t) {
    const auto tidx = t % fmap.size();
    const auto bnum = aprobs[t].size();
    for (size_t c = 0; c < fmap[tidx].size(); ++c) {
      const auto& blocks = fmap[tidx][c];

      double positive = 0, negative = 0;
      for (uint32_t b = 0; b < aprobs[t].size(); ++b) {
        if (blocks.end() != std::find(blocks.begin(), blocks.end(), b)) {
          positive += aprobs[t][b];
        } else {
          negative += aprobs[t][b];
        }
      }
      if (blocks.size() > 0) {
        positive /= blocks.size();
      } else {
        positive = 1;
      }
      if (bnum > blocks.size()) {
        negative /= bnum - blocks.size();
      } else {
        negative = 0;
      }
      const auto prob = positive * (1-negative);
      std::cout << prob << ' ';
    }
    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;
}