// Selección de proyectos: un greedy que falla, la red y lo que pasa con una capacidad finita.
#include <iostream>
#include <string>
#include <vector>

#include "projects.h"

namespace {

void print_choice(const std::vector<int>& chosen, const std::vector<std::string>& names) {
    if (chosen.empty()) std::cout << " (ninguno)";
    for (int i : chosen) std::cout << ' ' << names[static_cast<std::size_t>(i)];
    std::cout << '\n';
}

}  // namespace

int main() {
    const std::vector<std::string> names = {"tienda", "reportes", "app", "servidor", "api", "auditoria", "robot", "sensor"};
    const std::vector<long long> profit = {5, 4, 9, -6, -8, 3, 2, -5};
    const std::vector<Requirement> needs = {{0, 3}, {1, 3}, {2, 3}, {2, 4}, {5, 4}, {6, 7}};
    std::cout << "proyecto    ganancia\n";
    for (std::size_t i = 0; i < names.size(); i++) {
        std::cout << names[i];
        for (std::size_t k = names[i].size(); k < 12; k++) std::cout << ' ';
        std::cout << profit[i] << '\n';
    }
    std::cout << "requisitos: tienda, reportes y app piden servidor; app y auditoria piden api; robot pide sensor\n\n";

    std::cout << "Greedy, paquete por paquete:";
    std::vector<int> greedy = greedy_packages(profit, needs);
    print_choice(greedy, names);
    std::cout << "  ganancia: " << total_profit(profit, greedy) << '\n';

    ProjectChoice choice = best_projects(profit, needs);
    std::cout << "\nCorte mínimo:\n";
    std::cout << "  suma de ganancias positivas: " << choice.positive_total << '\n';
    std::cout << "  corte mínimo:                " << choice.min_cut << '\n';
    std::cout << "  ganancia máxima:             " << choice.value << '\n';
    std::cout << "  elegidos:";
    print_choice(choice.chosen, names);
    std::cout << "  fuerza bruta:                " << brute_projects(profit, needs) << '\n';

    std::cout << "\nSi los prerrequisitos tuvieran capacidad 1:\n";
    ProjectChoice broken = best_projects(profit, needs, 1);
    std::cout << "  la cuenta dice:              " << broken.value << '\n';
    std::cout << "  elegidos:";
    print_choice(broken.chosen, names);
    std::cout << "  ¿respetan los requisitos?    " << (is_closed(8, needs, broken.chosen) ? "sí" : "no") << '\n';
    std::cout << "  suma de sus ganancias:       " << total_profit(profit, broken.chosen) << '\n';
}
