// multiplex.c: multiplexación estadística frente a circuitos.
//
//   ./multiplex <Mbps del enlace> <Mbps por usuario> <p> <usuarios>
//
// Cada usuario transmite a su velocidad una fracción p del tiempo, de forma
// independiente de los demás. El número de usuarios activos sigue entonces una
// distribución binomial. El programa calcula cuántos caben con circuitos y qué
// tan probable es que, con conmutación de paquetes, se activen más de los que
// el enlace puede atender.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

// Devuelve P(X > limit) para X ~ Binomial(users, p), con 0 < p < 1.
// Cada término sale del anterior: P(k+1) = P(k) * (users-k)/(k+1) * p/(1-p).
static double tail_probability(int users, double p, int limit) {
    double term = pow(1 - p, users);
    double tail = 0;
    for (int k = 0; k <= users; k++) {
        if (k > limit) {
            tail += term;
        }
        term *= (double)(users - k) / (k + 1) * p / (1 - p);
    }
    return tail;
}

int main(int argc, char *argv[]) {
    if (argc != 5) {
        fprintf(stderr, "uso: %s <Mbps enlace> <Mbps usuario> <p> <usuarios>\n", argv[0]);
        return EXIT_FAILURE;
    }
    double link = atof(argv[1]);
    double per_user = atof(argv[2]);
    double p = atof(argv[3]);
    int users = atoi(argv[4]);
    if (link <= 0 || per_user <= 0 || p <= 0 || p >= 1 || users <= 0) {
        fprintf(stderr, "multiplex: se necesita enlace y usuario > 0, 0 < p < 1, usuarios > 0\n");
        return EXIT_FAILURE;
    }

    int circuits = (int)(link / per_user);
    printf("con circuitos caben: %d usuarios\n", circuits);
    printf("con paquetes y %d usuarios: en promedio %.1f activos\n", users, users * p);
    printf("P(mas de %d activos a la vez) = %.3e\n", circuits, tail_probability(users, p, circuits));
    return EXIT_SUCCESS;
}
