// Corre las cuatro reglas sobre los contraejemplos de los apuntes.
#include <iostream>
#include <string>
#include <vector>

#include "intervals.h"

namespace {

void print_classes(const std::vector<Interval>& classes) {
    for (const Interval& c : classes) std::cout << " [" << c.start << "," << c.finish << ")";
    std::cout << '\n';
}

void run_rule(const std::string& name, const std::vector<Interval>& result) {
    std::cout << "  " << name << ": " << result.size() << (is_valid(result) ? " (válida)" : " (INVÁLIDA)") << " ->";
    print_classes(result);
}

void report(const std::string& title, const std::vector<Interval>& classes) {
    std::cout << title << "\n  clases:";
    print_classes(classes);
    std::cout << "  óptimo por fuerza bruta: " << max_compatible_brute(classes) << '\n';
    run_rule("empieza antes", rule_earliest_start(classes));
    run_rule("dura menos   ", rule_shortest(classes));
    run_rule("menos cruces ", rule_fewest_conflicts(classes));
    run_rule("termina antes", select_by_finish(classes));
    std::cout << '\n';
}

}  // namespace

int main() {
    report("Contra empieza antes:", {{8, 18}, {9, 11}, {11, 13}, {13, 15}});
    report("Contra dura menos:", {{8, 12}, {12, 16}, {11, 13}});
    const std::vector<Interval> crowded = {
        {0, 2}, {2, 4}, {4, 6}, {6, 8},   // las cuatro de la solución óptima
        {1, 3}, {1, 3}, {1, 3},           // tres iguales entre las dos primeras
        {3, 5},                           // la del centro: solo dos cruces
        {5, 7}, {5, 7}, {5, 7}};          // tres iguales entre las dos últimas
    report("Contra menos cruces:", crowded);

    std::cout << "En esa lista, cruces de cada clase:\n";
    for (std::size_t i = 0; i < crowded.size(); i++) {
        std::cout << "  [" << crowded[i].start << "," << crowded[i].finish << "): " << conflicts(crowded, i)
                  << (in_some_optimum(crowded, i) ? "" : "  (no está en ninguna solución óptima)") << '\n';
    }
    const auto [low, high] = fewest_conflicts_range(crowded);
    std::cout << "Menos cruces, con cualquier forma de romper empates: entre " << low << " y " << high << '\n';
}
