Wednesday, December 20, 2006

funcion para generar numeros aleatorios, con todos los digitos distintos

El codigo para este articulo aplica a C#

Leyendo blogs, me encontre con este post (en italiano), donde Marco quiere escribir una funcion que le genere numeros aleatorios de 5 digitos, el resultado se requiere en un string, donde todos los digitos son diferentes, es decir, cada numero (de 5 digitos) generado, no puede tener 2 digitos iguales, la funcion que el escribio es la siguiente:

private string GetRandom()
{
Random rn = new Random();
string resultnum=string.Empty;
do
{
string a = rn.Next(0, 9).ToString();
if (resultnum.Contains(a)!=true)
resultnum = resultnum + a;
}
while (resultnum.Length<5); style="color: rgb(0, 0, 255);">return resultnum;
}

Inmediatamente me dio curiosidad por ver que areas que podria mejorar, y me puse a escribir una funcion que obtuviera el mismo resultado, pero en forma mas optimizada

cosas que saltan a mi mente inmediatamente son:

  1. concatenacion de strings
  2. el loop y la comparacion para encontrar numeros que no tengamos previamente

Entonces lo que quise lograr en mi funcion es: evitar la concatenacion, y ejecutar el loop exactamente 5 veces, esto es el resultado:

static char[] allNumbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
Random r = new Random();
public string GetRandom2() {

char[] result = new char[5];
int max = 9, pos=0;
for (int i=1; i<6; pos =" r.Next(0," style="color: rgb(0, 128, 0);">//*** swap positions
allNumbers[pos] ^= allNumbers[max];
allNumbers[max] ^= allNumbers[pos];
allNumbers[pos] ^= allNumbers[max--];
}
return new string(result);
}

La tecnica que use,

- fue tener un arreglo predefinido de caracteres con todos los digitos,

- luego tengo una variable max que uso para llamar el metodo Random.Next(0, max),

- en cada iteracion del loop decremento esta variable,

- y cambio el numero que resulto elegido a la ultima posicion, con esto lo dejo fuera de las posibilidades para la siguiente llamada

Estos cambios me dieron una ganancia realmente minima (3 milesimas por cada 1000 llamadas), luego se me ocurrio mover la declaracion de la variable Random afuera de la funcion, para que se reusara con cada llamada a este metodo, y eso si que me dio una ganancia tremenda, llamando la funcion 10,000 veces, el metodo original me da 114ms, y el metodo nuevo 6ms, asi que ahi era donde estaba realmente el problema, lo demas es casi insignificante =o(

Seguro alguien mas puede crear una funcion mas rapida, pero yo cumpli mi objetivo =o)

salu2

No comments: