Foros del Web » Programando para Internet » Javascript »

[APORTE] rotador aleatorio sin repetición pocas imágenes

Estas en el tema de [APORTE] rotador aleatorio sin repetición pocas imágenes en el foro de Javascript en Foros del Web. hacer un rotador aleatorio es sencillo. pero si el número de elementos es pequeño y queremos que no se repitan sucesivamente, se nos complica un ...
  #1 (permalink)  
Antiguo 08/10/2012, 13:44
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
[APORTE] rotador aleatorio sin repetición pocas imágenes

hacer un rotador aleatorio es sencillo. pero si el número de elementos es pequeño y queremos que no se repitan sucesivamente, se nos complica un poco

la idea esta sacada de este tema

para aquellos que aún no tienen claro el problema, veamoslo con un ejemplo
Cita:
var sec = [0,1,2];
(function cambiarImagen() {

var banners = new Array();
banners[0]= new Array("1156.png","http://www.enlace1.com");
banners[1]= new Array("1441.png","http://www.enlace2.com");
banners[2]= new Array("2192.png","http://www.enlace3.com");


var ad = Math.floor(Math.random() * banners.length);


console.log(ad);


setTimeout(function(){cambiarImagen()}, 2000);

})()
vemos que hay momentos en que el elemento se repite, con lo que si la temporización fuese de 30 segundo, veríamos ese elemento durante 1 minuto

la solución es usar algunas funciones para arrays
Cita:
var sec = [0,1,2];
var elim = [];
(function cambiarImagen() {

var banners = new Array();
banners[0]= new Array("1156.png","http://www.enlace1.com");
banners[1]= new Array("1441.png","http://www.enlace2.com");
banners[2]= new Array("2192.png","http://www.enlace3.com");


var ad = sec.splice(Math.floor(Math.random() * sec.length), 1)[0];

console.log(ad);

elim.push(ad);


if(sec.length == 0) {
sec = elim.slice(-3, -1);
}


setTimeout(function(){cambiarImagen()}, 2000);

})()
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}

Última edición por IsaBelM; 08/10/2012 a las 13:55
  #2 (permalink)  
Antiguo 08/10/2012, 15:52
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Hay una forma de hacerlo más sencillo, sin operaciones de arrays.
http://jsfiddle.net/marlanga/sg2Ja/1/

En vez de utilizar el índice generado al azar como índice absoluto, simplemente se lo sumo al índice que saqué en la vuelta anterior, teniendo cuidado de no sobrepasar los límites del array con una operación MOD.
  #3 (permalink)  
Antiguo 12/10/2012, 19:52
(Desactivado)
 
Fecha de Ingreso: noviembre-2002
Ubicación: Ciudad Autónoma de Buenos Aires
Mensajes: 2.367
Antigüedad: 22 años
Puntos: 317
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Hola todos.

Muy buenos los aportes, y especialmente tu idea, IsaBelM. Ésta es una pregunta muy repetida en el Foro de javascript, y a veces vienen aquí con ejemplos "que no les andan" y cuando los vemos nos agarramos la cabeza mientras huimos al grito desesperado de "¡ESTO NO ESTÁ PASANDO! ¡ESTO NO ESTÁ PASANDO!".

Al menos los que escribamos nosotros tendrán alguna 'garantía'. (Claro, mientras sigamos viniendo al Foro.)


Eso de que

Cita:
Iniciado por IsaBelM
... hay momentos en que el elemento se repite, con lo que si la temporización fuese de 30 segundo, veríamos ese elemento durante 1 minuto...
es totalmente cierto. Pero ocurre no solamente entre pocos baners, si hay muchos puede pasar igual. Hay menos probabilidades, pero es factible.
Y si estos baners son pagos, daría la idea de que alguno tiene privilegios, y su publicidad dura más tiempo.


Aprovecho para dejar otra forma, que sería una mezcla de los anteriores, porque no necesita verificar si hay repetición o si se terminó el array, pero usa el método splice(), y una alternativa al push().

Código:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<title>ROTADOR 1. </title>
<script type="text/javascript">
var banners = new Array();
 banners[0]= new Array("http://imageshack.us/a/img109/5243/nataliamolinero.jpg",
"http://imageshack.us/photo/my-images/109/nataliamolinero.jpg/");
 banners[1]= new Array("http://imageshack.us/a/img513/3887/pedroroth.jpg",
"http://imageshack.us/photo/my-images/513/pedroroth.jpg/");
 banners[2]= new Array("http://imageshack.us/a/img848/1629/christianamezcua.jpg",
"http://imageshack.us/photo/my-images/848/christianamezcua.jpg/");
 banners[3]= new Array("http://imageshack.us/a/img195/4783/urinegvi.jpg",
"http://imageshack.us/photo/my-images/195/urinegvi.jpg/");

var elige = [];

function rotar0() {
elige = banners.splice(Math.floor(Math.random() * (banners.length - 1)), 1);
	//alert(elige)
	//alert(banners)
document.getElementById( "muestra" ).src = elige[0][0];
document.getElementById( "enlace" ).href = elige[0][1];
document.getElementById( "ruta" ).innerHTML = elige[0][1];
banners[banners.length] = [elige[0][0], elige[0][1]];
	//alert(banners)
	document.getElementById( "ruta" ).style.color = 
	(document.getElementById( "ruta" ).style.color == "blue")? "red" : "blue";
setTimeout(rotar0, 2000);
}

onload = rotar0;
</script>
<style type="text/css">
p {text-align: center; }
</style>
</head>
<body>
<p>
<a href="#" id="enlace"><img src="" alt="" width=320 height=240 id="muestra"></a>
</p>
<p id="ruta"></p>
</body>
</html>
Como habrán notado, tiene una "trampa". El último baner de la serie es excluído ya en la primera vuelta.
Pero el sponsor no tiene por qué enterarse.


El sistema sigue siendo de random. Quiero decir, que de toda la lista de baners, se elige una al azar para mostrarla, y el escript no permite que aparezcan dos iguales seguidos.
Pero si bien el segundo no puede ser igual al primero, el tercero sí puede repetir al primero, porque ya no están seguidos.

Ésta es una gran diferencia con el sistema shuffle, que manda toda la serie de baners en un orden, y cuando ya pasó cada uno una vez, los muestra todos de nuevo en un orden distinto. Por supuesto, también podría lograrse que el último de una serie no se repitiese con el primero de la siguiente.
  #4 (permalink)  
Antiguo 13/10/2012, 07:37
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

de nuevo volvemos al uso de métodos para arrays

muy bueno lo de eliminarlo y una vez mostrado insertarlo en la última posición

habría que averiguar qué es más eficiente
Cita:
banners[banners.length] = [elige[0][0], elige[0][1]];
o
Cita:
banners.push([elige[0][0], elige[0][1]]);
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}
  #5 (permalink)  
Antiguo 13/10/2012, 08:16
(Desactivado)
 
Fecha de Ingreso: noviembre-2002
Ubicación: Ciudad Autónoma de Buenos Aires
Mensajes: 2.367
Antigüedad: 22 años
Puntos: 317
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por IsaBelM Ver Mensaje
de nuevo volvemos al uso de métodos para arrays

Es que son rápidos y muy prácticos. Te ahorran mil problemas, mientras sean compatibles.

muy bueno lo de eliminarlo y una vez mostrado insertarlo en la última posición

Gracias. Es algo de tu escuela : "la línea del menor esfuerzo". (¿Seguís poniendo código en 'citas'?)

habría que averiguar qué es más eficiente

banners[banners.length] = [elige[0][0], elige[0][1]];

o

banners.push([elige[0][0], elige[0][1]]);


push(), seguro. Por algunas milésimas de segundo. Pero ya que estamos poniendo ejemplos, quería mostrar otra variante para conseguir lo mismo.

Gracias por el +1. En realidad te lo merecés vos, que abriste el tema (ya lo pongo).

A marlanga no le doy +1 porque todavía no explicó cómo funciona el método de usar el resto de la división para sumar al índice de array.
  #6 (permalink)  
Antiguo 13/10/2012, 14:52
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por furoya Ver Mensaje
Gracias. Es algo de tu escuela : "la línea del menor esfuerzo". (¿Seguís poniendo código en 'citas'?)
te respondo con una nueva versión
Cita:
var banners = new Array();
banners[0]= new Array("1156.png","http://www.enlace1.com");
banners[1]= new Array("1441.png","http://www.enlace2.com");
banners[2]= new Array("2192.png","http://www.enlace3.com");

var intervalo = '';

(function cambiarImagen(antiguo) {

var nuevo = Math.floor(Math.random() * banners.length)

if (antiguo == nuevo) {
clearTimeout(intervalo);
cambiarImagen(nuevo);
} else {
console.log(nuevo);
intervalo = setTimeout(function(){cambiarImagen(nuevo)}, 2000);
}

})(banners.length);
se trata de comparar el valor que se está mostrando con el nuevo valor que se mostrará, y jugar con limpiar y restablecer el temporizador hasta que el antiguo y el nuevo valor sean distintos.

es posible que se pierdan unas milésimas de segundo, nada apreciable, al limpiar el temporizador e invocar de nuevo a la función.

en la primera invocación se le pasa el largo del arreglo, para así asegurarnos que el primer valor es aleatorio
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}

Última edición por IsaBelM; 13/10/2012 a las 14:57
  #7 (permalink)  
Antiguo 16/10/2012, 08:43
(Desactivado)
 
Fecha de Ingreso: noviembre-2002
Ubicación: Ciudad Autónoma de Buenos Aires
Mensajes: 2.367
Antigüedad: 22 años
Puntos: 317
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Eso está bien para galerías con muchos elementos de array, porque hay menos posibilidades de que ¡justo! se nos repita el mismo. Aunque alguien se va a venir a quejar del consumo de recursos.


En temas paralelos estuvimos ahondando sobre el método shuffle. Hay varias formas de lograrlo, cada una con más o menos ventajas, y hacerla "fácil" quizá requiera algunas concesiones de nuestra parte.

Muestro una variante del ejemplo que puse en #3

Código:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<title>ROTADOR 2. </title>
<script type="text/javascript">
var banners = new Array();
 banners[0]= new Array("http://imageshack.us/a/img109/5243/nataliamolinero.jpg",
"http://imageshack.us/photo/my-images/109/nataliamolinero.jpg/");
 banners[1]= new Array("http://imageshack.us/a/img513/3887/pedroroth.jpg",
"http://imageshack.us/photo/my-images/513/pedroroth.jpg/");
 banners[2]= new Array("http://imageshack.us/a/img848/1629/christianamezcua.jpg",
"http://imageshack.us/photo/my-images/848/christianamezcua.jpg/");
 banners[3]= new Array("http://imageshack.us/a/img195/4783/urinegvi.jpg",
"http://imageshack.us/photo/my-images/195/urinegvi.jpg/");

var elige = [];
var limite = banners.length;

function rotar0() {
limite--;
elige = banners.splice(Math.floor(Math.random() * limite), 1);
	//alert(elige)
	//alert(banners)
document.getElementById( "muestra" ).src = elige[0][0];
document.getElementById( "enlace" ).href = 
document.getElementById( "ruta" ).innerHTML = elige[0][1];
banners.push([elige[0][0], elige[0][1]]);
	//alert(banners)
	document.getElementById( "lista" ).innerHTML += elige[0][1]+"\r\n";

if (limite == 0){ 
	//alert(limite)
limite = banners.length;
banners.concat(elige); 
	//alert(banners)
elige = []; 
	//alert(elige)
	document.getElementById( "lista" ).innerHTML += "\r\n";
}
	document.getElementById( "ruta" ).style.color = 
	(document.getElementById( "ruta" ).style.color == "blue")? "red" : "blue";
setTimeout(rotar0, 2000);
}

onload = rotar0;
</script>
<style type="text/css">
p {text-align: center; }
</style>
</head>
<body>
<p>
<a href="#" id="enlace"><img src="" alt="" width=320 height=240 id="muestra"></a>
</p>
<p id="ruta"></p>

<textarea id="lista" rows=40 cols=70></textarea>
</body>
</html>
Lo que inmediatamente notamos aquí es que para evitar la repetición de la última imagen de una serie con la primera del que le sigue, se usa un método simple y casi reprobable : dejar un elemento "fijo", que mantenga su posicion mientras el resto, sí, es ordenado de manera aleatoria y sin repetirse entre ellos.
Este banner fijo (la cuarta imagen) se muestra en el mismo orden en todas las series y sirve de separador. En la práctica, a menos que alguien se ponga a contar la secuencia, da la ilusión de que aparece en medio de las otras.

Después de notar eso, ya encontramos otro inconveniente : si las imágenes son elegidas al azar, perfectamente puede repetirse la secuencia de las tres primeras ... de casualidad.

Y esto ya va siendo más difícil de evitar. A menos que carguemos toda la secuencia previamente antes de mostrarla, y comparemos con la anterior. (tal como sugeriste en el post #6, IsaBelM.)

O que simulemos un orden aleatorio, que no sea aleatorio.

Cuanta más cantidad de baners haya, más fácil será disimular estas licencias de programación.


juego en JS

Duda con shuffle
  #8 (permalink)  
Antiguo 16/10/2012, 12:02
Avatar de ryugen
Colaborador
 
Fecha de Ingreso: agosto-2008
Ubicación: Rosario, Santa Fe
Mensajes: 350
Antigüedad: 16 años, 2 meses
Puntos: 187
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Acá mi versión: http://jsfiddle.net/sg2Ja/2/

Derivada de marlanga.

Caracteristicas:
--> Selección aleatoria de elementos
--> No se repiten consecutivamente elementos
--> Se muestran todos los elementos antes de volver a comenzar a la aleatoriedad de los elementos
  #9 (permalink)  
Antiguo 17/10/2012, 15:18
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

furoya, a ver si es esto lo que intentas hacer.

se muestran los elemento barajados en todas las series y el último elemento de la serie, no es el mismo de la serie siguiente. si te fijas, se me ha ocurrido usar sort() para hacer el shuffle. en caso que el primer elemento de la nueva serie sea el mismo que el último elemento de la serie anterior, vuelvo a mandar a barajar
Cita:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<title>ROTADOR 2. </title>

<style type="text/css">
p {text-align: center; }
</style>
</head>
<body>



<textarea id="lista" rows=40 cols=80></textarea>


<script type="text/javascript">
var banners = new Array();
banners[0]= new Array(0, "http://imageshack.us/a/img109/5243/nataliamolinero.jpg",
"http://imageshack.us/photo/my-images/109/nataliamolinero.jpg/");
banners[1]= new Array(1, "http://imageshack.us/a/img513/3887/pedroroth.jpg",
"http://imageshack.us/photo/my-images/513/pedroroth.jpg/");
banners[2]= new Array(2, "http://imageshack.us/a/img848/1629/christianamezcua.jpg",
"http://imageshack.us/photo/my-images/848/christianamezcua.jpg/");
banners[3]= new Array(3, "http://imageshack.us/a/img195/4783/urinegvi.jpg",
"http://imageshack.us/photo/my-images/195/urinegvi.jpg/");


var elige = [], counter = 0, counter2 = 1, ultimo = 999, intervalo = '';

Array.prototype.barajar = function() {
elige = this.sort(function() {return (Math.round(Math.random()) -.5);});
rotar0();
}






function rotar0() {

if (counter2 % 4 == 0) {
ultimo = elige[counter % elige.length][0];
document.getElementById("lista").innerHTML += elige[counter % elige.length][1]+ " - " + elige[counter % elige.length][0] + " - " + ultimo +"\r\n\r\n";
clearTimeout(intervalo);
counter2 = 1;
var intervalo2 = setTimeout(function() {banners.barajar()}, 2000);


} else {

if (counter2 == 1 && ultimo == elige[counter % elige.length][0]) {
document.getElementById("lista").innerHTML += "repetido\r\n\r\n";
elige = [];
banners.barajar();
} else {

document.getElementById("lista").innerHTML += elige[counter % elige.length][1]+ " - " + elige[counter % elige.length][0] + " - " + ultimo + ' - ' + elige[0][0] +"\r\n";
counter++;
counter2++;
intervalo = setTimeout(function() {rotar0()}, 2000);
}
}



}

onload = banners.barajar();
</script>
</body>
</html>
ryugen no vi que habías posteado otra versión a la de furoya. te comento el inconveniente que tiene

el código de marlanga no es tan aleatorio como puede parecer. nunca entrará en el bombo, el elemento cuya posición sea la misma que el parámetro pasado. lo cual está bien por que te garantiza que nunca se repetirán consecutivamente. en contra prestación sabemos que unos de los elementos nunca va a aparecer en la primera vuelta. por lo tanto, cuando usas el código de marlanga, la secuencia nunca podrá empezar por el color rojo

por si no he logrado explicarme
Cita:
var datos=[["rojo","red"],["verde","green"],["azul","blue"]];
var div = document.getElementById("test");
function cambiar(i){
i=(i+Math.floor(Math.random()*(datos.length-1)+1))%datos.length;
div.style.background=datos[i][1];
div.innerHTML=datos[i][0];

setTimeout(function(){cambiar(0);},1000);
}

cambiar(0);
siempre se mostraría el verde o el azul. aunque de inicio le pases un número superior al largo del array, seguirá sin mostrarse uno, el último
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}

Última edición por IsaBelM; 17/10/2012 a las 17:00
  #10 (permalink)  
Antiguo 18/10/2012, 02:02
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Eso se arregla haciendo la primera llamada (la última linea del script) con

cambiar(-1);
  #11 (permalink)  
Antiguo 18/10/2012, 05:02
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por marlanga Ver Mensaje
Eso se arregla haciendo la primera llamada (la última linea del script) con

cambiar(-1);
en tal caso, azul (el último) nunca se mostraría de inicio
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}
  #12 (permalink)  
Antiguo 19/10/2012, 06:48
Avatar de ryugen
Colaborador
 
Fecha de Ingreso: agosto-2008
Ubicación: Rosario, Santa Fe
Mensajes: 350
Antigüedad: 16 años, 2 meses
Puntos: 187
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por marlanga Ver Mensaje
Eso se arregla haciendo la primera llamada (la última linea del script) con

cambiar(-1);
Se soluciona iniciando la función cambiar con un número aleatorio

Código Javascript:
Ver original
  1. cambiar(Math.floor(Math.random() * datos.length));

Ver: http://jsfiddle.net/sg2Ja/3/

Puede arrancar por cualquier valor, incluso por el rojo.

Saludos
  #13 (permalink)  
Antiguo 19/10/2012, 07:09
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

ahora es aleatorio, pero continua ocurriendo lo mismo si el array contiene 4 elementos, 3 de ellos parten con un 33,333333.... % de posibilidades de aparecer de inicio y el otro (el aleatorio) con un 0%. la paridad está en que los 4 elementos partan con un 25% de posibilidades de aparecer de inicio.

podemos seguir dando vueltas hasta que echemos la pota. pero no se logrará cambiar ese hecho, por que el problemas radica aquí
Cita:
i=(i+Math.floor(Math.random()*(datos.length-1)+1))%datos.length;
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}
  #14 (permalink)  
Antiguo 19/10/2012, 10:20
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por IsaBelM Ver Mensaje
en tal caso, azul (el último) nunca se mostraría de inicio
Eso me pasa por "programar" de oidas sin probar los cambios xd.

http://jsfiddle.net/marlanga/sg2Ja/4/
Bueno, con este cambio está solucionado.

Y sí, el código lo único que hace es evitar que se repita el último elemento, pero sin "costosas" operaciones de arrays, sólo jugando con el índice.


En cuanto a función de barajar:

Código Javascript:
Ver original
  1. Array.prototype.barajar = function() {
  2. elige = this.sort(function() {return (Math.round(Math.random()) -.5);
  3. }


No está bien balanceada. Por ejemplo, aquí explican por qué. http://sroucheray.org/blog/2009/11/a...ffle-an-array/

la mejor forma de mezclar un array ya fue comentada en este tema:
http://www.forosdelweb.com/f13/duda-...uffle-1017974/
  #15 (permalink)  
Antiguo 19/10/2012, 13:20
Avatar de emprear
Colaborador
 
Fecha de Ingreso: junio-2007
Ubicación: me mudé
Mensajes: 8.388
Antigüedad: 17 años, 4 meses
Puntos: 1567
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Creo que estamos en uno de esos casos en los que la función debe de ser ajustada al objetivo a lograr. Aquí la universabilidad no cabe.
Las funciones que se han mostrado funcionan bien, algunas más optimizadas que otras, pero todas cumplen su cometido
Hacer un random sin repetición, de acuerdo, pero para que?
Dos casos típicos,
el reparto de una baraja, las cartas se reparten al azar y obviamente no puede haber 2 cartas iguales
un sorteo (con premios del uno al diez) en los que obtenemos 10 ganadores, con numeros que no pueden repetirse
Pero aquí se partió de un ejemplo aplicado al uso de baners rotativos, que deben ser distribuidos equitativamente en la presentación, ya no estamos hablando de un array que se mezcla y recorre al azar tan solo una vez (las cartas vuelven al mazo para ser mezcladas una vez terminada la partida) sino que estamos repitiendo el ciclo. Podemos como mucho solucionar el problema de que el primer banner del 2º ciclo sea el mismo que el último del 1º. En ese contexto lograr una "equidad" completa en la muestra de los banners es practicamente imposible, esta solo será conseguida si los mismos se muestran secuencialmente en el orden original.
Me pregunté entonces cual sería la mejor opción a utilizar en este caso, es decir para crear un rotador aleatorio sin repetición pocas imágenes (o muchas, sería lo mismo), y mantener la distribución "equitativa", que es el punto fundamental. Sin desmerecer para nada los excelentes trabajos que han expuesto, sencillamente, mezclaría nuestro array de imágenes al cargar la página y luego lo recorería sin volver a mezclarlo, una y otra vez

Código HTML:
Ver original
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  2.    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4. <title>Cambiar banners</title>
  5. <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  6. <script type="text/javascript">
  7. //<![CDATA[
  8. var mezclar = function(n){
  9. for(var j, x, i = n.length; i; j = Math.floor(Math.random() * i), x = n[--i], n[i] = n[j], n[j] = x);
  10. return n;
  11. }
  12.  
  13. var banners = ['1', '2', '3', '4', '5', '6', '7'];
  14. mezclar(banners);
  15. var banner_actual = 0;
  16. var Cambiar = function(){
  17.     var p= "";
  18. if (banner_actual == banners.length) {
  19. banner_actual = 0;
  20. }
  21. var cambio =banner_actual++;
  22. if(cambio === 6){
  23. p = "<br \/>";
  24. }
  25. document.getElementById('banner').innerHTML +=  banners[cambio] + '<br \/>' +  p;
  26. var t = setTimeout(Cambiar, 1000);
  27. }
  28. window.onload = Cambiar;
  29. //]]>
  30. </head>
  31. <div id="banner"><!-- banners --></div>
  32. </body>
  33. </html>


Espero se entienda la idea
Saludos
__________________
La voz de las antenas va, sustituyendo a Dios.
Cuando finalice la mutación, nueva edad media habrá
S.R.

Última edición por emprear; 19/10/2012 a las 13:45
  #16 (permalink)  
Antiguo 19/10/2012, 14:07
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Tu idea está clara. Pero tras la primera vuelta, ya no sería aleatorio. Seguirías un patrón de repetición.
Ahora podrías decir "bueno, en cada vuelta, vuelvo a mezclar el array.
Bien, pero corres peligro de que el último elemento del array antes de mezclar sea el primer elemento del array re-mezclado.
Y si añades más código para evitar ésto, entonces puedes compararlo con las soluciones que ya se han puesto por aquí.
  #17 (permalink)  
Antiguo 19/10/2012, 14:11
Avatar de IsaBelM
Colaborador
 
Fecha de Ingreso: junio-2008
Mensajes: 5.032
Antigüedad: 16 años, 5 meses
Puntos: 1012
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por emprear Ver Mensaje
Sin desmerecer para nada los excelentes trabajos que han expuesto, sencillamente, mezclaría nuestro array de imágenes al cargar la página y luego lo recorería sin volver a mezclarlo, una y otra vez
antes de publicar mi último código es justamente lo que programé, pero al leer mas detenidamente la propuesta de furoya, lo modifiqué a su propuesta
__________________
if(ViolenciaDeGénero) {alert('MUJER ASESINADA');}
  #18 (permalink)  
Antiguo 19/10/2012, 14:36
Avatar de emprear
Colaborador
 
Fecha de Ingreso: junio-2007
Ubicación: me mudé
Mensajes: 8.388
Antigüedad: 17 años, 4 meses
Puntos: 1567
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por marlanga Ver Mensaje
Tu idea está clara. Pero tras la primera vuelta, ya no sería aleatorio. Seguirías un patrón de repetición.
Ahora podrías decir "bueno, en cada vuelta, vuelvo a mezclar el array.
Bien, pero corres peligro de que el último elemento del array antes de mezclar sea el primer elemento del array re-mezclado.
Y si añades más código para evitar ésto, entonces puedes compararlo con las soluciones que ya se han puesto por aquí.
Esa es la propuesta para una aplicación de este tipo, que no sea aleatorio salvo para la carga de página, vamos a un ejemplo concreto, si ofrezco a un cliente aparecer en un sistema de banners rotativos, se quejará si antes de la aparición de su banner otro se repite 2 veces, de la misma manera, se quejará si cada vez que se carga la página, aparece siempre el mismo, esto último tampoco es 100% controlable salvo que estemos almacenando en alguna parte valores, ip del cliente etc, pero al menos dificulta al máximo las posibilidades de repetición del banner inicial.
@IsabelM
A decir verdad mi enfoque se me ocurrió luego de ver ese código.

Saludos
__________________
La voz de las antenas va, sustituyendo a Dios.
Cuando finalice la mutación, nueva edad media habrá
S.R.
  #19 (permalink)  
Antiguo 19/10/2012, 15:07
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Yo hablaba de lo que tiene que hacer el algoritmo, no de sus posibles casos de uso.
  #20 (permalink)  
Antiguo 19/10/2012, 16:20
(Desactivado)
 
Fecha de Ingreso: noviembre-2002
Ubicación: Ciudad Autónoma de Buenos Aires
Mensajes: 2.367
Antigüedad: 22 años
Puntos: 317
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Y no está mal, marlanga. De hecho, te dejé el camino preparado para que vinieras aquí con el planteo. (Que ryugen te madrugara, ya no es mi culpa.)
Pero no vamos a matarnos por una secuencia de banners. Mi idea -y lo consulté con la autora del tema- era aprovechar éste para mostrar ejemplos prácticos y desarmables para los novatos. Que entiendan cómo van funcionando y evolucionando a versiones más complejas. Y después de dónde salen estos algoritmos y funciones que estamos (bah, están, yo ni me metí) diseccionando.
Pero, insisto, después. Empezar con esto ahora es espantar al que se anime a venir con curiosidad a aprender algo que puede no saber.
¿Quieren ponerse a debatir sobre la constante de Chaitin? ¡Perfecto! Pero vamos de a poco. ¿Sí?

Y antes de que me olvide ¿se puede saber para qué meten los códigos en un sitio ajeno a FdW?.
Después a ese sitio lo venden, o lo cierra el FBI, y nos quedamos sin nada. Entiendo que usen un servicio de virtual disk para imágenes, que no se pueden guardar en el Foro ¡pero aquí te ofrecen una colección de etiquetas para publicar código! ¡no te están obligando a meterlo entre etiquetas de cita! (Hola IsaBelM )

Encima que le pesqué algún bug. Lo que muestra en el iframe no siempre es lo mismo que vamos a ver si lo probamos desde nuestro editor. Pero bueno, la vista en tiempo real sería una comodidad aceptable. Poner el código fuente fuera de nuestros temas, no.

Iba a comentar sobre alguna de las funciones que están probando, y alguna que están por probar, pero ya se me hizo largo el post y no quiero aburrir.
Los dejo arrancándose las mechas.
  #21 (permalink)  
Antiguo 19/10/2012, 16:22
Avatar de emprear
Colaborador
 
Fecha de Ingreso: junio-2007
Ubicación: me mudé
Mensajes: 8.388
Antigüedad: 17 años, 4 meses
Puntos: 1567
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Cita:
Iniciado por marlanga Ver Mensaje
Yo hablaba de lo que tiene que hacer el algoritmo, no de sus posibles casos de uso.
No quiero hacer de esto una discusión Bizantina, pero yo en particular le doy un uso al código que uso. De todas formas te felicito por tu esfuerzo.
Saludos
__________________
La voz de las antenas va, sustituyendo a Dios.
Cuando finalice la mutación, nueva edad media habrá
S.R.
  #22 (permalink)  
Antiguo 20/10/2012, 07:28
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Iba a escribir algunas líneas más. Pero qué diantres, el que quiera entender, que entienda.
  #23 (permalink)  
Antiguo 29/10/2012, 16:52
(Desactivado)
 
Fecha de Ingreso: noviembre-2002
Ubicación: Ciudad Autónoma de Buenos Aires
Mensajes: 2.367
Antigüedad: 22 años
Puntos: 317
Respuesta: [APORTE] rotador aleatorio sin repetición pocas imágenes

Aprovechando que aún estamos vivos, quise resolver el planteo de asegurarnos el recorrido por todos los banners antes de volver a pasarlos. Claro que eso ya estába asegurado, por ejemplo, al retirar del conjunto cada uno de los que mostrábamos para meterlo en uno nuevo. Cuando el primero se termina, lo reemplazamos con el segundo que queda entonces vacío; y empezamos de nuevo.
Las objeciones son que eligiendo al azar puede repetirse el último de la vuelta anterior con el primero de la siguiente. Pero como en javascript podemos "saber" cuando se cambia de conjunto o array, con hacer la comparación antes de empezar la nueva secuencia ya podemos mandar el elegido de nuevo al conjunto (en otra posición) y entonces sí recomenzar la rotación.
Otra objeción, que es la que me dejó pensando, es la de cómo mezclar lo "suficiente" para que la misma imagen entre una secuencia y la otra no estuviesen cerca, y que no diese la impresión de que alguna pasa "dos veces" antes que otra (recordemos que no hay una marca para saber dónde termina una serie y empieza la otra, y para quien mira, "su secuencia" empieza con la imagen a la que llegó a prestarle atención primero).

Por supuesto; este problema no tiene solución. Lo único que podemos hacer si la cantidad de banners es muy grande, es ordenarlos en todas las combinaciones posibles y pasar siempre esa misma serie. Ya no sería aleatoria, pero estaría bien repartida. Y como son muchos, nadie se va a acordar de cómo vienen ... por lo que parece al azar.

Si fuese una combinación, el cálculo es medianamente sencillo. Ya lo hicimos en el foro varias veces.

permutaciones

Todas las combinaciones posibles de 012 ej 111, 101, 121..

Pero como son permutaciones sin repetición, el cálculo de la cantidad es facil, si son 4 baners sólo hay 24 combinaciones posibles
Banners₍₄,₄₎

4 × 3 × 2 × 1 = 24
Extraer de la cantidad de combinaciones posibles sólo las que no tienen ninguna imagen repetida, ya no me salió.
Pero no es que no se pueda. A lo bruto sale (en un enlace que hay más arriba, maycolalvarez linkea un ejemplo). Yo pretendía resolverlo con una 'fórmula'. Basado en la lista que se crea con parseInt("333",4).

Como no pude, aprovecho el post para mencionar otro caso de rotación, donde no se muestra una sino varias imágenes juntas, y no deben repetirse entre ellas.

Creación código para poner 3 imágenes aleatoria

Transición de cinco imágenes.

Etiquetas: imagenes, repeticion, rotador, aleatoria
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 8 personas




La zona horaria es GMT -6. Ahora son las 15:51.