Cree una función que genere un conjunto de números aleatorios distintos extraídos de un rango. El orden de los elementos en el conjunto no es importante (incluso se pueden ordenar), pero debe ser posible que el contenido del conjunto sea diferente cada vez que se llama a la función.
La función recibirá 3 parámetros en el orden que desee:
- Recuento de números en el conjunto de salida
- Límite inferior (incluido)
- Límite superior (incluido)
Suponga que todos los números son enteros en el rango de 0 (inclusive) a 2 31 (exclusivo). La salida se puede devolver de la forma que desee (escriba en la consola, como una matriz, etc.)
Juzgar
Los criterios incluyen las 3 R's
- Tiempo de ejecución : probado en una máquina Windows 7 de cuatro núcleos con cualquier compilador que esté disponible de forma libre o fácil (proporcione un enlace si es necesario)
- Robustez : la función maneja casos de esquina o caerá en un bucle infinito o producirá resultados no válidos: una excepción o error en una entrada no válida es válida
- Aleatoriedad : debe producir resultados aleatorios que no son fácilmente predecibles con una distribución aleatoria. Usar el generador de números aleatorios incorporado está bien. Pero no debe haber sesgos obvios o patrones predecibles obvios. Necesita ser mejor que ese generador de números aleatorios utilizado por el Departamento de Contabilidad en Dilbert
Si es robusto y aleatorio, todo se reduce al tiempo de ejecución. No ser robusto o aleatorio perjudica enormemente su clasificación.
code-challenge
fastest-code
number
random
Jim McKeeth
fuente
fuente
Respuestas:
Pitón
Probablemente solo reinventé un algoritmo bien conocido, pero la idea es realizar (conceptualmente) una combinación aleatoria parcial de Fisher-Yates del rango
lower..upper
para obtener eln
prefijo de longitud de un rango aleatorio uniforme.Por supuesto, almacenar todo el rango sería bastante costoso, por lo que solo almaceno los lugares donde se han intercambiado los elementos.
De esta manera, el algoritmo debería funcionar bien tanto en el caso de que esté muestreando números de un rango estrecho (por ejemplo, 1000 números en el rango 1..1000), como en el caso de que esté muestreando números de un rango amplio .
No estoy seguro de la calidad de la aleatoriedad del generador incorporado en Python, pero es relativamente simple intercambiar cualquier generador que pueda generar enteros de manera uniforme desde algún rango.
fuente
python 2.7
no estoy seguro de cuál es tu posición usando métodos aleatorios incorporados, pero aquí tienes de todos modos. agradable y corto
editar: acabo de notar que a range () no le gusta hacer grandes listas. da como resultado un error de memoria. verá si hay alguna otra forma de hacer esto ...
edit2: range fue la función incorrecta, xrange funciona. El número entero máximo es en realidad
2**31-1
para pythonprueba:
fuente
C
Devuelve una matriz que contiene x entradas aleatorias únicas entre min y max. (la persona que llama debe liberar)
Funciona generando x enteros aleatorios secuenciales en el rango, luego barajándolos. Agregue un
seed(time)
lugar en la persona que llama si no desea los mismos resultados en cada ejecución.fuente
Rubí> = 1.8.7
fuente
R
fuente
La pregunta no es correcta. ¿Necesita un muestreo uniforme o no? En el caso de que se necesite un muestreo uniforme, tengo el siguiente código en R, que tiene una complejidad promedio O ( s log s ), donde s es el tamaño de la muestra.
Por supuesto, uno puede reescribirlo en C para un mejor rendimiento. La complejidad de este algoritmo se discute en: Rouzankin, PS; Voytishek, AV Sobre el costo de los algoritmos para la selección aleatoria. Métodos Monte Carlo Appl. 5 (1999), no. 1, 39-54. http://dx.doi.org/10.1515/mcma.1999.5.1.39
Puede buscar en este documento otro algoritmo con la misma complejidad promedio.
Pero si no necesita un muestreo uniforme, que solo requiere que todos los números muestreados sean diferentes, entonces la situación cambia dramáticamente. No es difícil escribir un algoritmo que tenga O ( s ) de complejidad promedio .
Ver también para muestreo uniforme: P. Gupta, GP Bhattacharjee. (1984) Un algoritmo eficiente para muestreo aleatorio sin reemplazo. International Journal of Computer Mathematics 16: 4, páginas 201-209. DOI: 10.1080 / 00207168408803438
Teuhola, J. y Nevalainen, O. 1982. Dos algoritmos eficientes para muestreo aleatorio sin reemplazo. / IJCM /, 11 (2): 127–140. DOI: 10.1080 / 00207168208803304
En el último artículo, los autores usan tablas hash y afirman que sus algoritmos tienen O ( s ) complejidad. Hay un algoritmo más rápido de tabla hash, que pronto se implementará en pqR (R bastante rápido): https://stat.ethz.ch/pipermail/r-devel/2017-October/075012.html
fuente
APL,
1822 bytesDeclara una función anónima que toma dos argumentos
⍺
y⍵
.⍺
es el número de números aleatorios que desea,⍵
es un vector que contiene los límites inferior y superior, en ese orden.a?b
seleccionaa
números aleatorios entre 0-b
sin reemplazo. Al tomar⍵[1]-⍵[0]
obtenemos el tamaño del rango. Luego elegimos los⍺
números (ver más abajo) de ese rango y agregamos el límite inferior. En C, esto sería⍺
veces sin reemplazo. No se necesitan paréntesis porque APL funciona de derecha a izquierda.Suponiendo que he entendido las condiciones correctamente, esto falla los criterios de 'robustez' porque la función fallará si se le dan argumentos incorrectos (por ejemplo, pasar un vector en lugar de un escalar como⍺
).En el caso de que
⍺
sea un vector en lugar de un escalar,1↑⍺
toma el primer elemento de⍺
. Para un escalar, este es el escalar en sí. Para un vector, es el primer elemento. Esto debería hacer que la función cumpla con los criterios de 'robustez'.Ejemplo:
fuente
{⍵+⍺?⎕-⍵}
debería ser suficiente, donde la solicitud es para el límite superior y el argumento derecho es el límite inferiorScala
compilar y ejecutar:
La segunda línea ejecutará 200 pruebas con 15 valores de 0 a 100, porque Scala produce un código de bytes rápido pero necesita algo de tiempo de inicio. Entonces 200 comienza con 15 valores de 0 a 100 consumiría más tiempo.
Muestra en un solo núcleo de 2 Ghz:
Lógica:
Usando los números aleatorios y recursivos incorporados en el rango (max-min), sumando min y comprobando, si el tamaño del conjunto es el tamaño esperado.
Crítica:
fuente
Esquema
No estoy seguro de por qué necesita pasar 3 parámetros ni por qué necesito asumir cualquier rango ...
fuente
R
fuente
C ++
Este código es mejor cuando se extraen muchas muestras del rango.
fuente
max-min
sea mucho más grande quen
. Además, la secuencia de salida está aumentando monotónicamente, por lo que obtiene una aleatoriedad de muy baja calidad pero sigue pagando el costo de llamarrand()
varias veces por resultado. Un aleatorio aleatorio de la matriz probablemente valdría el tiempo de ejecución adicional.Q (19 caracteres)
Luego use f [x; y; z] como [conteo de números en el conjunto de salida; punto de partida; tamaño del rango]
por ejemplo, f [5; 10; 10] generará 5 números aleatorios distintos entre 10 y 19 inclusive.
Los resultados anteriores muestran el rendimiento en 100,000 iteraciones de elegir 100 números aleatorios entre 1 y 10,000.
fuente
R, 31 o 40 bytes (dependiendo del significado de la palabra "rango")
Si la entrada tiene 3 números,
a[1], a[2], a[3]
y por "rango" quieres decir "una secuencia entera de un [2] a un [3]", entonces tienes esto:Si tiene una matriz
n
de la cual está a punto de volver a muestrear, pero bajo la restricción de los límites inferior y superior, como "valores de remuestreo de la matriz dadan
del rangoa[1]...a[2]
", utilice esto:¡Estoy bastante sorprendido de por qué el resultado anterior no se jugó considerando la muestra incorporada con instalaciones de reemplazo! Creamos un vector que satisface la condición del rango y lo volvemos a muestrear.
fuente
0:(2^31)
causa unError: cannot allocate a vector of size 16.0 Gb
Javascript (usando una biblioteca externa) (64 bytes / 104 bytes ??)
Enlace a lib: https://github.com/mvegh1/Enumerable/
Explicación del código: la expresión Lambda acepta min, max, count como args. Cree una colección de tamaño n y asigne cada elemento a un número aleatorio que se ajuste a los criterios mínimo / máximo. Convierta a matriz JS nativa y devuélvala. También ejecuté esto en una entrada de tamaño 5,000,000, y después de aplicar una transformación distinta todavía mostraba 5,000,000 elementos. Si se acuerda que esto no es lo suficientemente seguro como garantía de distinción, actualizaré la respuesta
Incluí algunas estadísticas en la imagen a continuación ...
EDITAR: La imagen a continuación muestra el código / rendimiento que garantiza que cada elemento será distinto. Es mucho más lento (6.65 segundos para 50,000 elementos) en comparación con el código original anterior para los mismos argumentos (0.012 segundos)
fuente
K (oK) , 14 bytes
Solución:
Pruébalo en línea!
Ejemplo:
Explicación:
Toma 3 entradas implícitas por especificación:
x
, recuento de números en el conjunto de salida,y
, límite inferior (inclusive)z
, límite superior (inclusive)Notas:
También un políglota
q/kdb+
con un conjunto adicional de paréntesis:{y+((-)x)?1+z-y}
(16 bytes).fuente
Axioma + su biblioteca
La función f () anterior devuelve como error la lista vacía, en el caso f (n, a, b) con a> b. En otros casos de entrada no válida, no se ejecuta con un mensaje de error en la ventana de Axiom, porque el argumento no será del tipo correcto. Ejemplos
fuente