Ver Mensaje Individual
  #9 (permalink)  
Antiguo 04/08/2007, 07:30
Avatar de derkenuke
derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 21 años, 1 mes
Puntos: 45
Re: hora punta en una tienda sabiendo entrada y salida de los clientes

Vale bueno, ya he simplificado el problema, y he disminuído en mucho el tiempo de cálculo. Decir que el script anterior daba el resultado incorrecto porque los clientes no salían en el minuto que decía su .salida, sino en el minuto después. Se corrige dejando sólo un < en vez de <= en la función:
Código:
Number.prototype.estaEntre = function(a,b) {
    return ( (Math.min(a,b)<=this) && (this<Math.max(a,b)) );
}
Lo sé porque hice a mano los primeros no se cuántos clientes, y algo pasaba. También porque contrasté el nuevo script con el viejo.


Pues en este nuevo script he conseguido tener en el array clientesDentro sólo los datos de las horas en los que hay eventos (y no cada minuto como tenía antes). En consecuencia este array es 1/3 de tamaño que el de la anterior versión, y su tiempo de creación y de recorrido es mucho más corto.

Lo que he hecho:
  • 1) En el array entradasSalidas guardo un registro de todo lo que ocurre en la tienda, es decir, guardo todos los eventos que ocurren. Recorro todos los .entrada y todos los .salida de los clientes. Lo que guardo aquí es "+3" si han entrado 3 clientes, o "-2" si han salido dos clientes, así de cómodo ("+0" si han salido los que han entrado en ese minuto en cuestión).
  • 2) Ahora sí, en el array clientesDentro guardo todos los eventos ordenaditos, y transformo los "+3" y "-2" en una variable que nos diga el número de clientes que hay dentro de la tienda a esa hora. Es decir, que al principio nos encontramos con "+1" en el primer evento, luego el primer registro de clientesDentro contiene 1. Si en el próximo minuto nos encontramos "+3", quiere decir que hay dentro de la tienda esos 3 más el que estaba, luego almacenamos 4. Así con todos los minutos.
  • 3) Ya sólo nos queda localizar el máximo de clientesDentro (que será el mismo array que en la primera versión, pero sin datos duplicados) y su hora punta.

El código de las funciones base (librería) es exactamente igual que la primera versión (aunque podríamos ahorrarnos un par de funciones...), y el nuevo código (con comentarios generosos) sería este:
Código PHP:
var inicioScript = new Date();


// REGISTRO DE LAS ENTRADAS Y SALIDAS DE LOS CLIENTES EN LA TIENDA (17:00 - 20:00)
var clientes = new Array();
clientes[0] = { entrada"17:05"salida"17:22" 
clientes[1] = { entrada"17:08"salida"17:31" 
clientes[2] = { entrada"17:11"salida"17:15" 
clientes[3] = { entrada"17:14"salida"17:42" 
clientes[4] = { entrada"17:24"salida"17:26" 
clientes[5] = { entrada"17:24"salida"17:28" 
clientes[6] = { entrada"17:29"salida"17:46" 
clientes[7] = { entrada"17:30"salida"17:58" 
clientes[8] = { entrada"17:46"salida"17:54" 
clientes[9] = { entrada"17:48"salida"18:03" 
clientes[10] = { entrada"17:49"salida"17:56" 
clientes[11] = { entrada"18:00"salida"18:23" 
clientes[12] = { entrada"18:02"salida"18:19" 
clientes[13] = { entrada"18:13"salida"18:30" 
clientes[14] = { entrada"18:33"salida"18:49" 
clientes[15] = { entrada"18:38"salida"18:47" 
clientes[16] = { entrada"18:58"salida"19:09" 
clientes[17] = { entrada"19:04"salida"19:26" 
clientes[18] = { entrada"19:07"salida"19:34" 
clientes[19] = { entrada"19:19"salida"19:27" 
clientes[20] = { entrada"19:23"salida"19:25" 
clientes[21] = { entrada"19:27"salida"19:39" 
clientes[22] = { entrada"19:31"salida"19:31" 
clientes[23] = { entrada"19:31"salida"19:45" 
clientes[24] = { entrada"19:36"salida"19:50" 
clientes[25] = { entrada"19:40"salida"19:56" 
clientes[26] = { entrada"19:43"salida"20:01" 
clientes[27] = { entrada"19:45"salida"19:49" 
clientes[28] = { entrada"19:48"salida"20:01" 
clientes[29] = { entrada"19:49"salida"20:09" }




// Lo que voy a hacer es rellenar un registro entradasSalidas. Contendrá cada hora y los clientes que entran y salen cada hora:
//        entradasSalidas["14:28"] = "+3" si es que han entrado 3 clientes a esa hora, 
//        entradasSalidas["14:34"] = "-2" si es que han salido 2 personas
var entradasSalidas = new Array();
for(var 
i=0i<clientes.lengthi++) {
    
// Hay que comprobar que existe el registro antes. Si existe hay que contabilizar lo que había entrado (o salido) más lo nuevo que entra (o sale).
    
var laEntrada entradasSalidasclientes[i].entrada ];
    if( 
laEntrada != undefined )            //ya existía en el registro! --> Ponemos el cómputo ( lo que había antes +1 entrando )
        
entradasSalidasclientes[i].entrada ] = "+"+ eval( laEntrada+"+1");
    else
        
entradasSalidasclientes[i].entrada ] = "+1";            //caso normal, no existe, lo inicializamos
    // Recomprobamos si el registro existe, porque puede hacer sido modificado (si clientes[i].entrada == clientes[i].salida)
    
var laSalida entradasSalidasclientes[i].salida ];
    if( 
laSalida != undefined )            //ya existía en el registro! --> Ponemos el cómputo ( lo que había antes -1 saliendo )
        
entradasSalidasclientes[i].salida ] = "+"+ eval( laSalida+"-1");
    else
        
entradasSalidasclientes[i].salida ] = "-1";            //caso normal, no existe, lo inicializamos
}

/*
// IMPRESIÓN DE entradasSalidas
e("entradasSalidas:");
for(var j in entradasSalidas ) {
    e("entradasSalidas["+j+"] = "+entradasSalidas[j]);
}
e(""); e(""); 
*/

// Recorro todos los minutos entre las 17 y las 20:30 para evaluar quién está dentro en cada minuto
fecha = new Date();
var 
anterior=0;
var 
clientesDentro = new Array();
for( 
fecha.ponLaHora("17:00"); fecha.queHoraEs()!="20:31"fecha.sumaUnMinuto() ) {
    var 
hActual fecha.queHoraEs();
    var 
eS entradasSalidashActual ];        // entradaSalida actual
    
if( eS != undefined ) {
        
//e("existe "+hActual+" --> "+eS);
        
clientesDentro[hActual] = eval( anterior eS );
        
anterior clientesDentro[hActual];
    }
}


// IMPRESIÓN DE CLIENTESDENTRO
e("CLIENTESDENTRO:");
for(var 
j in clientesDentro ) {
    
e("clientesDentro["+j+"] = "+clientesDentro[j]);
}
e(""); e(""); 


// Ahora tengo clientesDentro con sólo las horas en las que se producen eventos, voy a sacar los valores e intervalos máximos
var valMax 0
var horasPuntas = new Array();
for( var 
i in clientesDentro ) {
    if( 
clientesDentro[i] > valMax ) {        // máximo encontrado
        
valMax clientesDentro[i];            //reasignamos valMax
        
horasPuntas = new Array(i);            //reinicializamos horasPuntas
    
}
    else if( 
clientesDentro[i] == valMax ) {    // horaPunta encontrada
        
horasPuntashorasPuntas.length ] = i;        //añadimos una horaPunta más
    
}
}

e("LAS HORAS PUNTAS HAN SIDO "+horasPuntas+" EN LA QUE HABÍA "+valMax+" CLIENTES EN LA TIENDA.");

var 
finScript = new Date();
e("Tiempo para el cálculo: "+(finScript.getTime()-inicioScript.getTime())+" ms"); 

Tampoco es más largo que la versión anterior, pero si muy eficiente:
  • IE6 >> 16 ms.
  • FF2 >> 125 ms.
Siendo su salida:
Cita:
LAS HORAS PUNTAS HAN SIDO 19:48,19:49 EN LA QUE HABÍA 5 CLIENTES EN LA TIENDA.


Bueno, a falta de más simplificación, creo que ya hemos llegado a donde quería llegar más o menos.


Si alguien quiere comentar/aportar algo, nuevas ideas, nuevas proposiciones, por supuesto se lo agradeceré.



Un saludo
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.