// Compara las cuatro reglas con la fuerza bruta en instancias al azar.
#include <iomanip>
#include <iostream>
#include <random>
#include <vector>

#include "intervals.h"

int main() {
    std::mt19937 rng(404);
    const int rounds = 20000;
    int invalid = 0;
    int bad_start = 0;
    int bad_short = 0;
    int bad_conflicts = 0;
    int bad_finish = 0;
    for (int round = 0; round < rounds; round++) {
        const int n = 2 + static_cast<int>(rng() % 11);  // de 2 a 12 clases
        std::vector<Interval> classes;
        for (int i = 0; i < n; i++) {
            const int start = static_cast<int>(rng() % 20);
            const int length = 1 + static_cast<int>(rng() % 8);
            classes.push_back({start, start + length});
        }
        const std::size_t best = static_cast<std::size_t>(max_compatible_brute(classes));
        const auto by_start = rule_earliest_start(classes);
        const auto by_short = rule_shortest(classes);
        const auto by_conflicts = rule_fewest_conflicts(classes);
        const auto by_finish = select_by_finish(classes);
        if (!is_valid(by_start) || !is_valid(by_short) || !is_valid(by_conflicts) || !is_valid(by_finish)) invalid++;
        bad_start += by_start.size() != best;
        bad_short += by_short.size() != best;
        bad_conflicts += by_conflicts.size() != best;
        bad_finish += by_finish.size() != best;
    }
    std::cout << rounds << " instancias de 2 a 12 clases\n";
    std::cout << "respuestas inválidas de cualquier regla: " << invalid << '\n';
    std::cout << "instancias en que la regla no llega al óptimo:\n";
    const auto line = [&](const char* name, int bad) {
        std::cout << "  " << name << std::setw(7) << bad << "  (" << std::fixed << std::setprecision(2)
                  << 100.0 * bad / rounds << " %)\n";
    };
    line("empieza antes", bad_start);
    line("dura menos   ", bad_short);
    line("menos cruces ", bad_conflicts);
    line("termina antes", bad_finish);
}
