Intervalos semiabiertos [inicio, fin)
Quien sale a las 10 no coincide con quien entra a las 10: el fin no cuenta.
[[9, 10], [10, 11], [11, 12]]
Un algoritmo de barrido que encuentra el momento de máximo aforo entre 300.000 reservas en unos 150 ms. El mismo código se ejecuta en tu navegador, en el servidor y en los tests.
01 · El algoritmo, paso a paso
Cada reserva se convierte en +1 al empezar y −1 al terminar. Los eventos se ordenan por tiempo, con los fines antes que los inicios, y todos los de un mismo instante se aplican antes de medir el aforo.
02 · Decisiones
Las reglas que fijé ante lo ambiguo y cómo trato los casos límite. El resultado de cada
ejemplo lo calcula en vivo la misma función maxOccupancy() que pasa los tests.
[inicio, fin)Quien sale a las 10 no coincide con quien entra a las 10: el fin no cuenta.
[[9, 10], [10, 11], [11, 12]]
En un mismo instante proceso primero las salidas y aplico todo el grupo antes de medir. Nunca cuento a alguien que ya se ha ido.
[[1, 5], [2, 5], [5, 9], [5, 9], [5, 9]]
No fusiono tramos contiguos con el mismo aforo: el pico termina en cuanto entra o sale alguien.
[[1, 4], [2, 6], [4, 9]]
Recorro el tiempo hacia delante y solo actualizo con un «>» estricto, así que el primer pico se queda.
[[5, 7], [1, 3], [6, 8], [2, 4]]
Sin reservas devuelvo [0, null, null]. Ordeno una lista nueva de eventos: el array de entrada nunca se modifica.
[]
[5, 5) está vacía: nadie ocupa la sala. Si generara eventos, recortaría el pico de otras reservas.
[[3, 10], [5, 5]]
Es un dato corrupto y darle la vuelta sería adivinar. Prefiero fallar pronto con RangeError (400 en la API) e indicar qué reserva está mal.
[[1, 2], [8, 3]]
Texto, NaN, Infinity o pares incompletos lanzan TypeError. Con NaN la ordenación fallaría en silencio.
[[1, "2"]]
Dos reservas idénticas son dos personas que reservaron el mismo hueco.
[[1, 5], [1, 5]]
Solo importa el orden. Los números son exactos hasta 2⁵³; un timestamp en milisegundos ronda 1,7·10¹².
[[-10, -2], [-5, 3]]
03 · En el servidor
Un servidor node:http llama a maxOccupancy. El generador
simula una semana de gimnasio: horas punta hacia las 8:00 y las 19:00, con los tiempos
en minutos desde el lunes a las 00:00. Todo el trabajo pesado va en un Web Worker, así
que la página nunca se congela.
04 · Rendimiento
Las dos versiones se ejecutan en tu navegador con los mismos datos. La de fuerza bruta se detiene en 16.000 reservas; a partir de ahí se extrapola, porque tardaría minutos.
| Reservas | Barrido | Ingenua | × |
|---|---|---|---|
| Pulsa «Empezar la carrera» | |||
05 · API
POST /api/max-occupancy con un array JSON de reservas, o
{ "bookings": [...] }.
Petición
Respuesta
{
"result": [3, 11, 12],
"maxOccupancy": 3,
"peakStart": 11,
"peakEnd": 12,
"bookings": 3,
"elapsedMs": 0.021
}
Códigos de respuesta
TypeError) o inicio > fin (RangeError)Por dentro
node:http: sin frameworks ni dependencias