// Cuenta las comparaciones de una búsqueda con distintos factores de carga.
// Uso: load_experiment archivo_de_palabras
#include <algorithm>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <random>
#include <string>
#include <vector>

#include "chain_table.h"
#include "word_file.h"

void measure(const std::vector<std::string>& words, std::size_t m, std::size_t n) {
    ChainTable<int> table(m, fnv1a);
    for (std::size_t i = 0; i < n; i++) {
        table.set(words[i], 1);
    }
    // Las n primeras están en la tabla. Las n siguientes, no.
    double hits = 0;
    double misses = 0;
    for (std::size_t i = 0; i < n; i++) {
        hits += static_cast<double>(table.comparisons_for(words[i]));
        misses += static_cast<double>(table.comparisons_for(words[n + i]));
    }
    double alpha = table.load_factor();
    double count = static_cast<double>(n);
    std::printf("%6zu %7zu %6.2f %9.2f %9.2f %9.2f %9.2f\n", m, n, alpha, hits / count, 1 + alpha / 2, misses / count, alpha);
}

int main(int argc, char** argv) {
    if (argc != 2) {
        std::cerr << "uso: load_experiment archivo_de_palabras\n";
        return 1;
    }
    std::vector<std::string> words = read_words(argv[1]);
    std::mt19937 rng(11);
    std::shuffle(words.begin(), words.end(), rng);
    std::printf("%6s %7s %6s %9s %9s %9s %9s\n", "m", "n", "alfa", "acierto", "1+alfa/2", "fallo", "alfa");
    measure(words, 100, 300);
    for (std::size_t n : {512u, 1024u, 2048u, 3072u, 5120u, 10240u, 102400u}) {
        measure(words, 1024, n);
    }
}
