Reordenar una tabla con la función Rnd. Control de la función.
Tiempo de lectura: 4,5 minutos
Función: reordenar elementos de una tabla de manera cuasi aleatoria
Lector/a recomendado/a: Personas que necesiten realizar trabajos de nivel intermedio con Hoja de Cálculo, Visual Basic, Macros.
Nivel: intermedio. Conocimientos de Macros
Revisión rev1: se ha revisado la función (04/1272022 18:27), ya que hay un caso en el que al randomizar, la posición 1 queda en la posición 1, con lo que no habría randomización y en un caso posible, las 16 randomizaciones darían como resultado la tabla original. Se ha añadido un if else que añade probablemente iteraciones pero da un resultado de mejor calidad.
Si no sabes crear una macro, aquí Microsoft te enseña (->)
Pulsa aquí si empleas LibreOffice (->)
Tanto Microsoft como LibreOffice tienen una web muy completa, tanto como sus aplicaciones. Lo que hacemos en este blog es crear funciones de aplicación que nos sirven a todos/as para desarrollar código de manera más sencilla. Este código se puede copiar, pegar y funciona sin ninguna configuración adicional, salvo asignarle un nombre a la Hoja/Libro en la/el que funciona.
Como sabes si manejas hojas de cálculo, la función Rnd() devuelve un número aleatorio, por lo tanto viene bien para simular funciones completamente aleatorias.
Cuando lo que queremos es reordenar unos elementos de manera cuasi-aleatoria, no podemos aplicar la función simplemente, porque podríamos obtener elementos repetidos, al estar la función acotada en el mismo intervalo en el que estamos trabajando. La función Rnd no tiene memoria, por lo que te puede ofrecer varias veces seguidas el mismo valor, si la aplicas dentro de un bucle.
Si necesitas distribuir elementos de manera cuasi-aleatoria, es decir, aplicarle a cada uno una posición distinta, pero nunca dos elementos en la misma posición y nunca reasignar una posición a un elemento ya asignado, puedes aplicar este algoritmo.
Recorre una tabla de dos dimensiones, con n filas y 2 columnas, en la que vamos grabando de la izquierda a la derecha, los elementos que han sido aleatorizados.
Esta función, mejora al bucle simple while, en que siempre funcionas aleatorizando dentro de un rango en el que tienes elementos, nunca repitiendo elemento y solamente ejecutas la función Rnd el número de veces que necesitas.
Si aplicas un bucle while y te quedas esperando a que el random pase por todos los elementos de una tabla que tiene siempre los mismos elementos, podría darse el caso de que mantengas a tu procesador trabajando sin necesidad. En cada pasada, la función trabaja con un elemento menos. Con 16 elementos la diferencia puede ser nimia, pero si tu tabla tiene 300.000 elementos, lo que necesitas es que en cada iteración, estés trabajando con los elementos sobre los que debes trabajar y no sobre elementos ya gestionados.
Haz la prueba y verás la diferencia.
Este código emplea una hoja de cálculo llamada Token y necesita 16 celdas vacías en el rango AC5:AC20. Con pequeñas modificaciones puedes aleatorizar 32, 64, 128, 256 elementos.
El procedimiento es sencillo,
Carga la tabla con los 16 valores que quieres aleatorizar.
Posteriormente va randomizando sobre el número de posiciones que siguen sin gestionar, lo que llamamos elementos_pendientes, aumentando los elementos randomizados tras cada iteración. Cada vez que aumenta un elemento gestionado, disminuye un elemento pendiente.
La función calcula el Rnd() sobre los elementos disponibles trasladando cada elemento seleccionado a la columna de al lado y eliminándolo de la tabla inicial. Recoloca los elementos que están en posiciones posteriores, eliminando espacios vacíos, para tener un rango cada vez inferior en la tabla inicial, mejorando la eficiencia en cada iteración respecto a las iteraciones anteriores.
Permite mejoras a la comprensión, como emplear más variables de las que se emplean. Si estás aprendiendo a programar, es recomendable que veas todos los valores en el depurador. Recuerda que pulsando F8 puedes correr el programa paso a paso sin los fatídicos bucles infinitos.
Si quieres ver los elementos que van sumando a la tabla de la derecha, puedes emplear otra variable que se llame por ejemplo elementos_randomizados, que tendrá siempre el valor de la longitud de la tabla menos los elementos pendientes.
Recuerda que las variables las puedes definir en el momento que te hacen falta, pero si le das al procesador la posibilidad de reservar el espacio en memoria con la instrucción Dim, le das la posibilidad de funcionar mejor en términos generales.
Sub RandomizaTabla_rev1()
Dim a, b, celda, celda_inicial, d, elementos_pendientes, elementos_randomizados, j, longitud_tabla As Integer
longitud_tabla = 16
celda_inicial = 5
Dim tabla(15, 1)
For a = 0 To longitud_tabla - 1
tabla(a, 0) = a
Next
elementos_pendientes = longitud_tabla
Do While elementos_pendientes > 0
Randomize
b = elementos_pendientes * Rnd()
b = Int(b)
If b <> longitud_tabla - elementos_pendientes + 1 Then
j = tabla(b, 0)
tabla(longitud_tabla - elementos_pendientes, 1) = j
celda = "AC" & (longitud_tabla - elementos_pendientes + celda_inicial)
Worksheets("Token").Range(celda).Value = j + 1
For a = b + 1 To elementos_pendientes - 1
tabla(a - 1, 0) = tabla(a, 0)
Next
tabla(elementos_pendientes - 1, 0) = Vacío
elementos_pendientes = elementos_pendientes - 1
End If
Loop
End Sub
Esta web emplea 99,799kB de código html para transmitir 5.852 caracteres de texto plano. Una eficiencia de un 5,8%

Comentarios
Publicar un comentario