diff options
Diffstat (limited to 'tabulator/tabulator.cpp')
-rw-r--r-- | tabulator/tabulator.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/tabulator/tabulator.cpp b/tabulator/tabulator.cpp new file mode 100644 index 0000000..60cd680 --- /dev/null +++ b/tabulator/tabulator.cpp @@ -0,0 +1,159 @@ +#include <lib94/lib94.hpp> +#include <iostream> +#include <fstream> +#include <sstream> +#include <cstdio> +#include <vector> + +const int steps_to_tie = 1000000; + +int error(std::string msg, int rank) { + if (rank == 0) { + std::cerr << msg << std::endl; + return 1; + } + return 0; +} + +constexpr lib94::instruction background_instruction = { + .op = lib94::DAT, .mod = lib94::F, + .amode = lib94::DIRECT, .bmode = lib94::DIRECT, + .anumber = 0, .bnumber = 0 +}; + +int main(int argc, char **argv) { + + MPI_Init(&argc, &argv); + + int rank; + int size; + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + lib94::seed_prng(time(0) + rank); + + std::vector<std::string> filenames = {}; + + for (int i = 1; i < argc; ++i) + filenames.push_back(argv[i]); + + if (filenames.size() == 0) + return error("no files specified.", rank); + if (filenames.size() == 1) + return error("only one file specified.", rank); + + int count = filenames.size(); + lib94::warrior **warriors = new lib94::warrior *[count]; + for (int i = 0; i < count; ++i) { + try { + warriors[i] = lib94::compile_warrior_from_file(filenames[i]); + } + catch (const lib94::compiler_exception &ex) { + return error("could not compile " + filenames[i] + ": " + ex.message + " on line " + std::to_string(ex.source_line_number) + ".", rank); + } + if (!warriors[i]) + return error("could not open " + filenames[i] + ".", rank); + } + + int **wins_against = new int *[count]; + for (int i = 0; i < count; ++i) + wins_against[i] = new int[count]; + + int **rounds_against = new int *[count]; + for (int i = 0; i < count; ++i) + rounds_against[i] = new int[count]; + + for (int i = 0; i < count; ++i) + for (int j = i + 1; j < count; ++j) { + + const lib94::warrior *w1 = warriors[i]; + const lib94::warrior *w2 = warriors[j]; + + if (rank == 0) + std::cout << "running " << w1->name << " vs " << w2->name << "..." << std::endl; + + int w1_wins, w2_wins, rounds; + lib94::tabulate_mpi<true>(background_instruction, w1, w2, steps_to_tie, w1_wins, w2_wins, rounds, MPI_COMM_WORLD); + + if (rank == 0) + std::cout + << "results:\n " << w1->name << ": " << w1_wins << "\n " + << w2->name << ": " << w2_wins << "\n ties: " + << (rounds - w1_wins - w2_wins) << "\n\n"; + + wins_against[i][j] = w1_wins; + wins_against[j][i] = w2_wins; + + rounds_against[i][j] = rounds; + rounds_against[j][i] = rounds; + + } + + if (rank == 0) { + + unsigned column_width = 0; + unsigned name_width = 0; + for (int i = 0; i < count; ++i) + if (warriors[i]->name.size() > name_width) { + name_width = warriors[i]->name.size(); + column_width = name_width; + } + + unsigned number_width = 0; + for (int i = 0; i < count; ++i) + for (int j = 0; j < count; ++j) + if (i != j) { + unsigned width = std::to_string(rounds_against[i][j]).size(); + if (width > number_width) + number_width = width; + if (width * 2 + 3 > column_width) + column_width = width * 2 + 3; + } + + for (int i = 0; i < count; ++i) + warriors[i]->name.insert(0, column_width - warriors[i]->name.size(), ' '); + + std::string spaces, dashes; + spaces.resize(column_width, ' '); + dashes.resize(column_width, '-'); + + std::string first_spaces; + first_spaces.resize(name_width, ' '); + std::cout << ' ' << first_spaces; + for (int i = 0; i < count; ++i) { + std::cout << " | " << warriors[i]->name; + } + + std::string first_dashes; + first_dashes.resize(name_width, '-'); + std::cout << "\n-" << first_dashes; + for (int i = 0; i < count; ++i) + std::cout << "-+-" << dashes; + std::cout << "-\n"; + + for (int i = 0; i < count; ++i) { + std::string name = warriors[i]->name; + name.erase(0, column_width - name_width); + std::cout << ' ' << name; + for (int j = 0; j < count; ++j) + if (i == j) + std::cout << " | " << spaces; + else { + std::string num = std::to_string(wins_against[j][i]); + std::string den = std::to_string(rounds_against[j][i]); + num.insert(0, number_width - num.size(), ' '); + den.insert(0, number_width - den.size(), ' '); + std::string content = num + " / " + den; + content.insert(0, column_width - content.size(), ' '); + std::cout << " | " << content; + } + std::cout << '\n'; + } + + } + + MPI_Finalize(); + return 0; + +} |