Ver Mensaje Individual
  #20 (permalink)  
Antiguo 25/11/2013, 12:50
Avatar de marlanga
marlanga
 
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Número aleatorio pero evitando uno en particular

Hacer range para crear un array de valores consecutivos y un suffle al array para desordenarlo, y escoger después varios de esos números aleatorios, sólo tiene sentido si el número de elementos a extrar es una gran porción del conjunto total de números, por ejemplo si queremos obtener 50 valores distintos con un rango entre 1 y 100. Esta filosofía tiene una mejora, y es no hacer un shuffle, si no un array_rand, que saca valores al azar. Así mejoras algo el tiempo de ejecución, pero no el consumo de memoria, que sigue siendo disparatado en comparación al problema a resolver.

Si la porción de números a sacar es escasa, como este caso (queremos 5 de 49), la fuerza bruta es mejor porque además de consumir menos recursos de memoria (siempre consume menos), también tardará menos.

La evidencia:
http://ideone.com/CDC6om


Código PHP:
Ver original
  1. <?php
  2. function azarSuffle($min, $max, $cantidad) {
  3.     $numeros = range($min, $max);
  4.     shuffle($numeros );
  5.     return array_slice($numeros, 0, $cantidad);
  6. }
  7. function azarBruto($min, $max, $cantidad) {
  8.     $numeros=array();
  9.     while (count($numeros)<$cantidad){
  10.         $aleatorio=rand($min, $max);
  11.         if (!in_array($aleatorio, $numeros)) $numeros[]=$aleatorio;
  12.     }
  13.     return $numeros;
  14. }
  15. function azarMejor($min, $max, $cantidad) {
  16.     $numeros = range($min, $max);
  17.     return array_rand($numeros, $cantidad);
  18. }
  19.  
  20. $ini=round(microtime(true) * 1000);
  21. for ($i=0;$i<1000;$i++)
  22.     azarSuffle(1,49,5);
  23. $fin=round(microtime(true) * 1000);
  24. $tiempoSuffle=$fin-$ini;
  25.  
  26. $ini=round(microtime(true) * 1000);
  27. for ($i=0;$i<1000;$i++)
  28.     azarBruto(1,49,5);
  29. $fin=round(microtime(true) * 1000);
  30. $tiempoBruto=$fin-$ini;
  31.  
  32. $ini=round(microtime(true) * 1000);
  33. for ($i=0;$i<1000;$i++)
  34.     azarMejor(1,49,5);
  35. $fin=round(microtime(true) * 1000);
  36. $tiempoMejor=$fin-$ini;
  37.  
  38. echo "Con suffle: ".$tiempoSuffle."\n";
  39. echo "Fuerza bruta: ".$tiempoBruto."\n";
  40. echo "Mejor: ".$tiempoMejor;
  41. ?>
Resultado:
Código BASH:
Ver original
  1. Con suffle: 13
  2. Fuerza bruta: 7
  3. Mejor: 11

Última edición por marlanga; 25/11/2013 a las 13:03