Tarea
Dado un número entero positivo n
menor que el 2^30
especificado como entrada en cualquier forma que elija, su código debería generar un número entero aleatorio entre 0
e n
, inclusive. El número que genere debe elegirse uniformemente al azar . Es decir, cada valor de 0
a n
debe ocurrir con la misma probabilidad (ver Reglas y Advertencias).
Reglas y advertencias
Su código puede suponer que cualquier generador de números aleatorios integrado en su idioma o biblioteca estándar que afirma ser uniformemente aleatorio es de hecho uniforme. Es decir, no tiene que preocuparse por la calidad de la fuente aleatoria que está utilizando. Sin embargo,
- Debe establecer que si la fuente aleatoria que está utilizando es uniforme, entonces su código genera correctamente un entero aleatorio uniforme de
0
an
. - Cualquier argumento al llamar a una función aleatoria integrada o de biblioteca debe ser constante. Es decir, deben ser completamente independientes del valor de entrada.
- Su código puede terminar con probabilidad 1 en lugar de estar garantizado para terminar.
Notas
randInt(0,n)
no es válido ya que toma la entrada como argumento para una función incorporada o biblioteca.rand()%n
será no dar un número aleatorio uniforme en general. A modo de ejemplo dado por betseg, siintmax == 15
yn = 10
, a continuación, que será mucho más probable conseguir0-5
que6-10
.floor(randomfloat()*(n+1))
tampoco dará un número aleatorio uniforme en general debido al número finito de diferentes valores posibles de coma flotante entre 0 y 1.
code-golf
number
random
probability-theory
totalmente humano
fuente
fuente
rng()
proporciona0
-100
, sin = 75
, y la función esrng()%75
, entonces 0-25 será más común ...)Respuestas:
Máquinas x86 con
rdrand
instrucciones, 10 bytescodigo de maquina
La entrada está en el registro
rdi
y la salida enrax
.Esto respeta el SYS V AMD64 ABI, por lo que el código implementa efectivamente una función C
con entradas de 32 bits.
rdrand
Intel describe la instrucciónAl tratar con CSRNG, está implícito que la distribución es uniforme, de todos modos, citando el NIST SP 800-90A:
El procedimiento genera un número aleatorio y, si no es estrictamente mayor que la entrada, se devuelve.
De lo contrario, el proceso se reitera.
Como
eax
es de 32 bits,rdrand
devuelve un número entre 0 y 2 32 -1, por lo que por cada n en [0, 2 32 -1] el número de iteraciones esperadas es 2 32 / (n + 1) que se define para todos los n en [0, 2 30 ).fuente
jnc
de?rdrand
estableceCF
si los datos devueltos son válidos. Los datos pueden no ser válidos porque demasiadas solicitudes agotaron el grupo de entropía. Vea la entrada manual para rdrand y esto .Gelatina ,
76 bytes¡Gracias a @JonathanAllan por jugar golf en 1 byte!
No se puede ejecutar en TIO porque (16!)! Es un gran número.
Cómo funciona
fuente
Mathematica, 29 bytes
Basado en la respuesta de Dennis's Jelly .
No recomendaría realmente ejecutar esto.
2e9!
es un número bastante grande ...Resulta más corto generar un gran número que sea divisible por todas las entradas posibles y asignar el resultado al rango requerido con un módulo simple.
Muestreo de rechazo, 34 bytes
Mi antiguo enfoque que condujo a un código algo más interesante:
Muestreo básico de rechazo. ¡Inicializamos la salida a 13! (que es mayor que la entrada máxima 2 30 ) y luego reemplácelo repetidamente con un entero aleatorio entre 0 y 13. siempre que el valor sea mayor que la entrada.
fuente
Brachylog , 9 bytes
Pruébalo en línea!
Esto se usa
13!
como en la respuesta de Martin Ender (13ḟ
es un byte menos que2^₃₀
).ṙ
se implementa utilizandorandom_between/3
, que, al cavar su fuente, utiliza elrandom_float/0
que está vinculado alrandom/1
que utiliza el algoritmo Mersenne Twister que es uniforme para nuestros propósitos.Explicación
fuente
Prólogo (SWI) , 38 bytes
Trabajos por muestreo de rechazo.
Genere un número aleatorio entre 0 y 2 ^ 31-1 = 2147483647 hasta que se encuentre uno menor o igual a la entrada.
Siento que debería poder usar un corte en lugar de otro, pero no puedo ver cómo.
fuente
repeat
, pero termina siendo 3 bytes más largos ... No estoy seguro si hay una forma más corta de tener infinitos puntos de elección que repetir.,!.
forzar un retroceso, pero o lo recuerdo mal o no es aplicable a esta solución.Laberinto , 63 bytes
(Gracias a @MartinEnder por la ayuda con un poco de golf pesado aquí).
Labyrinth es un lenguaje 2D, y su única fuente de aleatoriedad se encuentra en una situación como la siguiente:
Suponga que el puntero de instrucción está en
x
y se mueve hacia abajo. Luego aterriza en el<
, que si la parte superior de la pila es 0 (que siempre es el caso en el programa real anterior) desplaza la fila actual a la izquierda por 1:El puntero de instrucciones ahora está en el
<
mueve hacia abajo. En un cruce, Labyrinth gira en función de la parte superior de la pila: lo negativo es girar a la izquierda, lo positivo es girar a la derecha y cero es avanzar. Si la parte superior de la pila sigue siendo cero en este punto, no podemos movernos hacia adelante o hacia atrás ya que no hay camino, por lo que Labyrinth se aleatorizará entre girar a la izquierda o girar a la derecha con la misma probabilidad.Esencialmente, lo que hace el programa anterior es usar la función de aleatoriedad para generar números de 100 bits (100 especificados por
#00
aquí) y continuar haciendo bucles hasta que genere un número<= n
.Para las pruebas, probablemente sea útil usar
#0"
en su lugar para números de 10 bits, siendo la"
ruta no operativa.Pruébalo en línea!Explicación aproximada:
fuente
Python, 61 bytes
Editar: actualizado para evitar la forma prohibida
Edit2: guardado 2 bytes, gracias @ JonathanAllan
Edit3: Pagué 2 bytes por una solución totalmente funcional, gracias de nuevo @JonathanAllan
Edit4: eliminado
f=
, ahorrando 2 bytesEdit5: guardado 1 byte más gracias a @ JonathanAllan
Edit6: guardado 2 bytes más gracias a @ JonathanAllan
A estas alturas, la culpa de Git me señalaría por las cosas malas, y JonathanAllan por las cosas que ayudan.
Edit7: cuando llueve, llueve - otros 2 bytes
Edit8: y otros 2 bytes
fuente
n
, pero puede guardar dos bytes cuando lo arregle usandofrom random import*
y soltandor.
....*(-~n*1.0/2**30))
lugar de...*((n+1)*1.0/2**30))
randrange
parece aceptar un flotador, ¡así quelambda n,x=2.**30:int(randrange(x)*-~n/x)
ahorra otros dos [editar ... cuatro]!Python 2 , 61 bytes
Pseudo-azar elige números enteros comprendidos entre 0 y k para todos los valores de k entre 0 y 2 31 - 2 , entonces toma el número entero correspondiente a k = n .
fuente
Lote, 64 bytes
%random%
solo da 15 bits de aleatoriedad, por lo que tengo que combinar dos números aleatorios. Loops hasta que el valor aleatorio se encuentre dentro del rango deseado, tan lento para bajon
; 98 bytes para una versión más rápida:fuente
n
?call
, invocar un script por lotes termina el script actual.MATL , 12 bytes
Gracias a @AdmBorkBork y a @Suever por decirme cómo deshabilitar el caché TIO.
Pruébalo en línea! .
Esto utiliza un método de rechazo : genera un número entero aleatorio de
0
a2^30-1
, y repite mientras excede la entradan
. Se garantiza que esto terminará con probabilidad1
, pero el número promedio de iteraciones es2^30/n
, y por lo tanto, lleva mucho tiempo paran
significativamente menor que2^30
.fuente
JavaScript (ES6),
5554 bytesGenera enteros en el rango [0 ... 2 k - 1] , donde k es el entero más pequeño de modo que 2 k es mayor que n . Se repite hasta que el resultado cae en [0 ... n] .
¿Por qué?
Esto se basa en los siguientes supuestos:
Internamente, los valores enteros pseudoaleatorios generados por el motor JS para alimentar
Math.random()
son uniformes en cualquier intervalo [0 ... 2 k -1] (con k <32 ).Una vez multiplicado por una potencia exacta de 2, los valores de flotación IEEE 754 devueltos por
Math.random()
todavía son uniformes durante dichos intervalos.Si alguien puede confirmar o refutar estas hipótesis, hágamelo saber en los comentarios.
Manifestación
Genera 1 millón de valores en [0 ... 2] y muestra las estadísticas de resultados.
Mostrar fragmento de código
fuente
Bash (+ coreutils), 44 bytes
/ dev / solución basada en urandom
Leerá enteros de 32 bits sin signo
/dev/urandom
y los filtraráawk
hasta que encuentre uno dentro de un rango determinado, luegosed q
abortará la tubería.fuente
Haskell, 70 bytes
No es un algoritmo muy eficiente pero funciona. Genera una lista infinita de enteros (o flotantes si es necesario, debido al sistema de tipos de Haskell) delimitada por [0,2 ^ 30] y toma el primero menor o igual que n. Para pequeños n esto puede llevar mucho tiempo. Los números aleatorios deben distribuirse uniformemente, como se especifica en la documentación para randomR lo que todos los números en el intervalo [0,2 ^ 30] deben tener la misma probabilidad (1 / (2 ^ 30 + 1)), por lo tanto, todos los números en [ 0, n] tienen la misma probabilidad.
Versión alternativa:
Esta versión es terrible pero ahorra un byte completo.
randoms
usa un rango arbitrario definido por el tipo para generar una lista infinita de números. Esto puede incluirabs
aspectos negativos, por lo que debemos mapearlo para forzarlos a ser positivos (o cero). Esto es extremadamente lento para cualquier valor de n que no sea absurdamente grande. EDITAR : Me di cuenta más tarde de que esta versión no está distribuida uniformemente porque la probabilidad de obtener 0 es peor que los otros números debido al uso deabs
. Para producir algún número,m
el generador podría producirm
o,-m
pero en el caso de 0, solo 0 funcionará, por lo tanto, su probabilidad es la mitad de los otros números.fuente
Jalea , 9 bytes
Pruébalo en línea!- ¡el código anterior no se ejecutará en TIO desde un rango de tamaño 16! debe construirse primero (¡sin mencionar el hecho de que luego deben barajarse y luego filtrarse!), por lo que esto es lo mismo en una escala mucho más pequeña, repetido 30 veces para una entrada de 3 con un límite de 10.
¿Cómo?
Nota: sería más de mil veces más eficiente para el mismo recuento de bytes si
ȷ⁵
hiciera lo que uno esperaría ingenuamente y devolvería diez a diez, pero ese no es el caso ya⁵
que no se evalúa como un diez literal para ser utilizado por el número literal,ȷ...
sino que se analizan dos literales separados,ȷ
con su exponente predeterminado de tres dando mil y⁵
diez.fuente
JDK 9 en jshell,
7559 bytesUso
OptionalInt
. Las reglas no especifican que el tipo de retorno debe ser primitivo y consideroOptionalInt
que es una representación válida del resultado.fuente
Optional
se acepta o no. Confirmaría con el póster si fuera usted. Además, no es necesario contar toda la tarea; solo la expresión lambda es suficiente.n
ynew Random()
.PHP, 30 bytes
Corre con
echo <N> | php -Rn '<code>'
.elige un número aleatorio entre 0 y
getrandmax()
(2 ** 31-1 en mi máquina de 64 bits);se repite mientras que es más grande que la entrada.
Esta puede tomar un tiempo ... mi AMD C-50 (1 GHz) necesitó entre 0.3 y 130 segundos para
N=15
.Una forma más rápida para el promedio
N
( 46 bytes ):o
toma
N+1
enteros aleatorios, los resume y toma el módulo conN+1
.El C-50 necesita aprox. 8 segundos para 1 millón de carreras.
Una solución no válida para 19 bytes :
fuente
PowerShell , 35 bytes
Pruébalo en línea!
Otro método de muestreo de rechazo. Este es un
for
bucle infinito , que establece el valor de$a
ser unRandom
número entero entre0
y1gb
(= 1073741824 = 2^30
), y se mantiene en bucle siempre y cuando ese entero sea-g
reatro at
la entrada$args
. Una vez que se completa el ciclo, simplemente ponemos$a
en la tubería y la salida es implícita.Nota: Esto llevará mucho tiempo si la entrada es un número pequeño.
fuente
Python 2 ,
7269 bytes-3 bytes gracias a xnor (anular el
id
incorporado como una variable)Pruébalo en línea!
randrange(2**30)
produce un número distribuido pseudo-uniformemente (Mersenne Twister 2 19937-1 ) del rango [0,2 30 ) . Comon
se garantiza que está por debajo de 2 30, esto simplemente se puede llamar repetidamente hasta que no sea mayor que la entrada. Tomará un tiempo esperado largo para valores muy bajos den
, pero generalmente funciona en un minuto incluso para entradas tan bajas como 50.fuente
r=''
como "infinito". O, mejor aún, no inicialicer
y en su lugar use enid
todas partesr
.Perl 6 , 29 bytes
Inspirado en la solución Mathematica de Martin Ender .
Genera una secuencia perezosa infinita de enteros aleatorios entre 0 y 2 ^ 30-1, y toma el primero que está entre 0 y la entrada.
Pruébalo en línea!
fuente
05AB1E , 11 bytes
Pruébalo en línea!
Explicación
Como la lista
[0 ... 2147483648]
es demasiado grande para TIO, el enlace usa1.000.000
lugar.Solución alternativa (en promedio) mucho más rápida de 11 bytes
Pruébalo en línea
Explicación
fuente
žJL.R%
para 6 a menos que me falte algo enorme. Presione 2 ^ 32, lista de 0 a 2 ^ 32, selección aleatoria. Módulo de entrada. Absolutamente arruinará la eficiencia que tiene.I
de 7 bytes para obtener los argumentos del módulo en el orden correcto (y talÝ
vez en lugar deL
), pero de lo contrario, esa es ciertamente una solución más corta. Vi a Dennis haciendo eso en su respuesta de Jelly, pero como esta fue mi primera idea, me quedé con esto. Como ese enfoque es diferente de esto, podría publicarlo como una respuesta separada.DI‹Ï
Evitaría el bucle.0
casi siempre daría como resultado un bucle casi infinito, lo que dificulta la terminación. Aunque la solución permite la posibilidad de terminar en todos los escenarios, no está garantizada debido a la aleatoriedad.Python 2, 89 bytes
Explicación
Esto es muy ineficiente, ya que crea 2 ^ 31 enteros, los baraja y los filtra.
No veo ningún punto en compartir un enlace TIO, donde está creando listas tan grandes, así que aquí hay un enlace TIO para
n
= 100.Pruébalo en línea!
fuente
Java 8,
8483807162 bytes-1 byte gracias a @ OliverGrégoire .
-3 bytes gracias a @Jakob .
-9 bytes convirtiendo Java 7 a Java 8.
-9 bytes cambiando
java.util.Random().nextInt(1<<30)
a(int)(Math.random()*(1<<30))
.Explicación:
Pruébalo aquí
NOTA: Obviamente, puede tomar mucho tiempo para entradas pequeñas.
Salida de ejemplo:
fuente
2^30
=1073741824
. Preferiste usar-1>>>1
(=2147483647
). Pero esto existe:1<<30
que es exactamente igual a2^30
; y es 1 byte más corto.int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}
?Math.random()
lugar dejava.util.Random().nextInt
.Python 3, 51 bytes
Aquí hay una solución de Python con una fuente aleatoria poco ortodoxa.
Pruébalo en línea!
Entonces, para romper esto.
Obtiene el número de entrada y lo agrega
1
.Crea el conjunto
{0, 1, 2, 3, 4, ... n}
para todos los resultados posibles.Toma el conjunto, lo convierte en una lista y toma el primer elemento.
Esto funciona porque en Python 3, PYTHONHASHSEED
set()
establece el orden de ( no se puede obtener, pero se establece en la ejecución del script).Es cierto que supongo que esta es una distribución uniforme, ya que el
hash()
valor se asigna aleatoriamente y estoy buscando elegir aleatoriamente el valor con un valor específicohash()
, en lugar de simplemente devolverlohash(input())
.Si alguien sabe si esta es una distribución uniforme, o cómo podría probarla, por favor comente.
fuente
C #, 57 bytes
Función anónima que devuelve un número entero entre 0 yn inclusive.
Cuanto menor sea el número de entrada, mayor será el tiempo para devolver un valor aleatorio.
Programa completo:
fuente
Next
no es estático.Bash + coreutils, 20 bytes
Golfed
seq 0 $ 1 | shuf | sed 1q
Shuf usará el siguiente código : para generar permutaciones:
que termina en
randint_genmax
que, a su vez, leerá algunos bytes de los datos aleatorios de la fuente de aleatoriedad de bajo nivel:
es decir, en el nivel bajo, no existe una dependencia directa entre el
shuf
valor de entrada y los datos leídos de la fuente de aleatoriedad (aparte de calcular la capacidad de memoria intermedia de bytes requerida).fuente
jot will arrange for all the values in the range to appear in the output with an equal probability
(eso es probablemente límite, pero aún así).SmileBASIC, 38 bytes
Genera números aleatorios hasta que obtiene uno que es más pequeño que la entrada.
fuente
Ruby,
23 15 23 3229 bytesCómo funciona:
1while [...];
ejecuta la declaración al menos una vez:1
anteswhile
actúa como un nopfuente
Ohmios, 26 bytes
Explicación:
fuente
Ir,
6361 bytesÚselo así:
Pruébelo en vivo en el patio de recreo
fuente
Golang,
847871 bytesMuestreo de rechazo simple.
Nota: dado que la semilla de matemáticas / rand es una constante 1, la persona que llama debe sembrar a menos que se desee un resultado constante.
Prueba: https://play.golang.org/p/FBB4LKXo1rYa no es prácticamente comprobable en un sistema de 64 bits, ya que devuelve una aleatoriedad de 64 bits y utiliza pruebas de rechazo.fuente
import."math/rand"
,Int31
está disponible en el espacio de nombres global y puede guardar 4 bytes, tambiénint
se garantiza que tenga al menos 32 bits, lo que le ahorrará otros 6 bytes:=
sintaxis para otros 3 bytesInt()
función en el paquete de rand, también, puede eliminar el espacio después deimport