Aleatoriedad con probabilidades
(Iba a publicar esto en Facebook, pero al final he pensado que ya que tengo un blog medio muerto, lo mínimo es desvariar un poco en él de vez en cuando)
Me encontraba esta mañana en el proceso de maquillarme (porque ser developer no está reñido con tener unas pestañas de infarto) cuando por algún motivo me he preguntado si sería muy complicado hacer una aplicación (muy sencillita) que ordenara listas aleatoriamente, pero teniendo en cuenta que algunos elementos de la lista tuviesen una prioridad más alta o más baja. Es decir, que fuera más probable que algunos elementos (con prioridad más alta) estuviesen más arriba en la lista, pero que eso no impidiera que otros elementos con menor prioridad estuviesen delante de ellos (aunque esto debería ser menos probable)
Así de primeras, lo que me ha venido a la cabeza es generar para cada elemento de la lista un número aleatorio (en el intervalo (0, 1], por ejemplo), y multiplicar por un coeficiente relaccionado con la prioridad (simplificando, pongamos 0.5: prioridad normal y 1: prioridad alta). Luego se ordenaría la lista en función del número resultante, de mayor a menor. En principio como el peso de los elementos de menor prioridad se reduce a la mitad (porque su coeficiente era 0.5) lo normal sería que estuviesen más abajo en la lista que los elementos de prioridad alta (que no varían, al multiplicar por 1). Ojo, sería lo normal, pero no sería imposible, como he dicho antes, que hubiese elementos de prioridad menor por encima de los de prioridad alta (nada impediría que un elemento de prioridad baja tenga un peso inicial de -por ejemplo- 0.8 que se convierte en 0.4 al final, y otro elemento de prioridad alta con peso de 0.35 -y este estaría por abajo en la lista al final-)
Sí, lo sé, es muy cutre. Otra posibilidad sería multiplicar dos veces por un número aleatorio (0, 1] a los elementos de menor prioridad (siempre se reducirían aunque no sabríamos cuánto). O (esta opción parece más elegante) utilizar distintas distribuciones normales con distintas funciones de densidad (y aparentemente esto existe en C++)
Soltada toda esta fumada mental, la pregunta es ¿a alguien se le ocurre algo mejor? Ahí debajo teneis los comentarios :D
9 comentarios
juanfra -
motagirl2 -
juanfra -
Bob: 100
Alice: 90
Peter: 50
Bob tendría el rango del 0 a 99, Alice de 100 a 189 y Peter de 190 a 240. Generas un número aleatorio entre 0 y 240 y miras que elemento tiene ese número.
Pequeño, rápido y fácil de entender. Si miras el código después de un año no te vas a quedar con cara de idiota pensando qué leches hace el código, cosas que me da a mí que si pasará con todas las soluciones overenginered que estoy viendo :P .
No he mirado cómo programarlo, pero al menos en python debe ser sencillo.
motagirl2 -
juanfra -
motagirl2 -
juanfra -
motagirl2 -
Miki -
Lo primero que se me ocurre es limitar el rango de aletoriedad. Así, los de alta prioridad podrían ser aleatorios entre 0.4 y 1.0, y los de baja prioridad entre 0.0 y 0.6.
Otra forma que se me ocurre es, tras obtener el valor aleatorio, aplicar un offset de +0.3 o -0.3, según la prioridad. Claro, esto puede dar resultados por encima de 1.0 y por debajo de 0.0, pero eso no importa, ¿no? Aunque me da la impresión de que este método no funcionará tan bien como el anterior.
Elegir la distribución aleatoria adecuada parece lo más correcto, pero estas cosas me dan mucha tirria y no se la deseo a nadie xD
Lo mejor que se me ocurre es que implementes un test para evaluar si una lista está "bien" ordenada (que cumpla los requisitos que quieres), y probar todos los algoritmos que has comentado y los que te sugieran con, por ejemplo, 1000 listas generadas con cada uno. Así podrás ver cuánto tiempo toman, cómo de bien se ordenan las listas... y te puedes quedar con el mejor.