Sobre la serie
En primer lugar, puede tratar esto como cualquier otro desafío de golf de código y responderlo sin preocuparse por la serie. Sin embargo, hay una tabla de clasificación en todos los desafíos. Puede encontrar la tabla de clasificación junto con más información sobre la serie en la primera publicación .
Aunque tengo un montón de ideas para la serie, los desafíos futuros aún no están establecidos en piedra. Si tiene alguna sugerencia, hágamelo saber en la publicación de sandbox relevante .
Hoyo 2: números de una distribución normal
¡No puedo creer que esto no se haya hecho todavía! Debes generar números aleatorios, a partir de una distribución normal . Algunas reglas (la mayoría de ellas probablemente están cubiertas automáticamente por la mayoría de las presentaciones, pero algunas están en su lugar para garantizar la consistencia de los resultados entre idiomas muy diferentes):
Debe tomar dos enteros no negativos como entrada : una semilla
S
y la cantidadN
de números que se devolverán. La salida debe ser una lista deN
números de coma flotante, extraída de una distribución normal con media 0 y varianza 1 . Cada vez que su envío recibe la misma semillaS
, debe producir el mismo número. En particular, si se llama una vez con y una vez con , las primeras entradas de las dos salidas deben ser idénticas. Además, al menos 2 16 valores diferentes de deberían producir secuencias diferentes.(S, N1)
(S, N2)
min(N1, N2)
S
Puede usar cualquier generador de números aleatorios incorporado que esté documentado para extraer números de una distribución (aproximadamente) uniforme , siempre que pueda pasarlo
S
y admita al menos 2 16 semillas diferentes. Si lo hace, el RNG debería poder devolver al menos 2 20 valores diferentes para cualquier número dado que le solicite.- Si su RNG uniforme disponible tiene un rango más pequeño, no es visible o admite muy pocas semillas, primero debe construir un RNG uniforme con un rango suficientemente grande sobre el incorporado o debe implementar su propio RNG adecuado utilizando la semilla. Esta página puede ser útil para eso.
- Si no implementa un algoritmo establecido para generar distribuciones normales, incluya una prueba de corrección. En cualquier caso, el algoritmo que elija debe producir una distribución normal teóricamente exacta (salvo las limitaciones del PRNG subyacente o los tipos de datos de precisión limitada).
- Su implementación debe usar y devolver números de punto flotante (al menos 32 bits de ancho) o números de punto fijo (al menos 24 bits de ancho) y todas las operaciones aritméticas deben usar el ancho completo del tipo elegido.
- No debe utilizar ninguna función integrada directamente relacionada con la distribución normal o las integrales gaussianas, como la función Error o su inversa.
Puede escribir un programa completo o una función y recibir información a través de STDIN, argumento de línea de comando, argumento de función o solicitud y producir salida a través del valor de retorno o imprimiendo en STDOUT (o la alternativa más cercana).
S
y N
serán enteros no negativos, cada uno menor de 2 20 . La salida puede estar en cualquier formato de lista o cadena conveniente y sin ambigüedades.
Este es el código de golf, por lo que gana el envío más corto (en bytes). Y, por supuesto, la presentación más corta por usuario también entrará en la tabla de clasificación general de la serie.
Tabla de clasificación
La primera publicación de la serie genera una tabla de clasificación.
Para asegurarse de que sus respuestas aparezcan, comience cada respuesta con un título, utilizando la siguiente plantilla de Markdown:
# Language Name, N bytes
¿Dónde N
está el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:
# Ruby, <s>104</s> <s>101</s> 96 bytes
(El idioma no se muestra actualmente, pero el fragmento requiere y analiza, y puedo agregar una tabla de clasificación por idioma en el futuro).
Respuestas:
Dyalog APL, 33 bytes
{(.5*⍨¯2×⍟?0)×1○○2×?0}¨⍳⎕⊣⎕rl←1+⎕
Box-Muller :
fuente
⎕rl
a serS+1
porque⎕rl←0
tiene un significado especial.+1
, todo lo que dice es que necesita admitir al menos 2 ^ 16 valores diferentes. Por lo tanto, trabajar correctamente en el rango [1..2 ^ 16] debería estar bien.R, 68 bytes
Esto utiliza la
runif()
función, que genera desviaciones aleatorias de una distribución uniforme. La semilla para la generación de números aleatorios se especifica usandoset.seed()
, que por defecto usa el algoritmo Mersenne-Twister con un período de 2 ^ 19937-1.El resultado es un vector R de longitud N que contiene las desviaciones normales estándar calculadas.
Esto utiliza el método Box-Muller: para dos variables aleatorias uniformes independientes U y V,
fuente
f=
(la función no necesariamente necesita ser nombrada, si las funciones sin nombre son algo en su idioma).Error: unexpected '}' in "f=fu...
Además, siempre recibo un mensaje de error , ¿estás seguro de que obtienes los mismos primeros números si llamasf(0,1)
yf(0,2)
?Dyalog APL,
4234Esta es una función que toma
S
como argumento izquierdo yN
como argumento derecho.Es una implementación de la transformación Box-Muller, utilizando el operador aleatorio incorporado de Dyalog APL
?
, que por defecto es un tornado de Mersenne que devuelve valores de 64 bits, lo que debería ser suficiente.Explicación:
⎕RL←⍺
: establece la semilla aleatoria en⍺
.?⍵2⍴0
: genera⍵
pares de números aleatorios entre 0 y 1.{
...}/
: aplica la siguiente función a cada par:(.5*⍨¯2×⍟⍺)×1○⍵×○2
: calcular elZ0
valor (sqrt(-2 ln ⍺)×cos(2π⍵)
).fuente
?0
devuelve un número de coma flotante entre 0 y 1.Perl, 67
Box-Muller como en otras entradas.
f
toma los parámetros en ordenS, N
.Utilizar:
fuente
Java,
164161bytesEsto toma la entrada a través de la función y la salida a través de stdout. Utiliza el método Box-Muller.
fuente
s=0;s++<n;
->;n-->0;
?Commodore 64 Basic,
767063 bytesComo el juego de caracteres PETSCII contiene algunos símbolos que no están presentes en Unicode, he realizado sustituciones:
/
=SHIFT+N
,┌
=SHIFT+O
,●
=SHIFT+Q
,╮
=SHIFT+I
,─
=SHIFT+E
Esto implementa la transformación estándar de Box-Muller para generar los números; Elegí la mitad sin (x) de la transformación porque Commodore 64 Basic tiene un acceso directo de dos caracteres para
sin()
, pero no paracos()
.Aunque el manual establece lo contrario, el valor del argumento
RND
sí es importante: si se pasa un número negativo, el generador de números aleatorios no solo se vuelve a sembrar, sino que se vuelve a sembrar con ese número . Esto hace que la siembra sea mucho más simple: en lugar de necesitarPOKE
cinco ubicaciones de memoria, simplemente necesito hacer una llamada de no hacer nadaRND
, lo que reduce el código de dos líneas / 121 bytes a 1 línea / 76 bytes.Editar: Golfé seis bytes al darme cuenta de que podía combinar las dos
INPUT
declaraciones, y que el espacio despuésTO
era opcional.Editar: Golfed otros siete: Commodore Basic, de hecho, tiene Pi como una constante incorporada, e incluso se puede escribir en un teclado moderno (
SHIFT+PgDn
en caso de que se lo pregunte).fuente
80386 código máquina, 72 bytes.
Hexdump del código:
Aquí está el código fuente (puede ser compilado por Visual Studio):
Aquí uso un generador de números aleatorios de Lehmer . Utiliza el siguiente algoritmo:
Aquí 4294967291 es un número primo grande (2 ^ 32-5), y 116 es un número pequeño (menos de 128; ver más abajo) que es su raíz primitiva . Elegí una raíz primitiva que tiene una distribución más o menos aleatoria de ceros y unos en representación binaria (01110100). Este RNG tiene el período máximo posible de 4294967290, si la semilla no es cero.
Los números relativamente pequeños que utilicé aquí (116 y 4294967291, que también se pueden representar como -5) me permiten aprovechar la
lea
codificación de instrucciones:Se ensambla en 3 bytes si los números pueden caber en 1 byte.
El uso de multiplicación y división
edx
yeax
como sus registros de trabajo, es por eso que hiceseed
el segundo parámetro a la función (lafastcall
convención de llamada usaedx
para pasar el segundo parámetro). Además, se pasa el primer parámetroecx
, que es un buen lugar para mantener un contador: ¡se puede organizar un bucle en 1 instrucción!Para convertir un número entero en un número de coma flotante, exploté la representación de números de coma flotante de precisión simple: si establezco los 9 bits altos (exponente) en el patrón de bits
001111111
y dejo los 23 bits bajos al azar, obtener un número aleatorio en el rango 1 ... 2. Tomé la idea de aquí . Para establecer los 9 bits más altos, utilicé algunos ajustes de bits enebx
:Para generar dos números aleatorios, utilicé un bucle anidado de 2 iteraciones. Lo organicé con
xor
:El código de punto flotante implementa la transformación Box-Muller .
fuente
Haskell, 118
144Ejemplo de uso:
El tipo de retorno de
random
está restringido aFloat
, lo que hacerandom
generar un flotante uniforme en [0, 1). A partir de entonces, es una fórmula simlpe box-muller con algo de magia sin sentido para la generación de listas.fuente
Golflua, 63
70Golflua información e instrucciones.
Devuelve una tabla que contiene los valores. En el ejemplo que estoy usando
~T.u( )
, que es lo mismo quereturn table.unpack( )
en lua.Se guardaron muchos caracteres configurando el entorno de la función en
M
(akamath
).fuente
SAS, 108
Ya publiqué una respuesta en R que es más corta que esta, pero hay muy pocas respuestas SAS en PPCG, entonces, ¿por qué no agregar otra?
Con algo de espacio en blanco:
Esto define una macro que se puede llamar como
%f(5, 3)
. La macro ejecuta un paso de datos que recorre los números enteros 1 a N, y en cada iteración calcula una desviación normal aleatoria usando Box-Muller y la imprime en el registro usando laput
declaración.SAS no tiene incorporado para pi, por lo que lo mejor que podemos hacer es aproximarlo con arctangent.
La
ranuni()
función (que está en desuso pero requiere un par de caracteres menos que la función más nueva) devuelve un número aleatorio de una distribución uniforme. La documentación de SAS no brinda muchos detalles sobre la implementación de RNG, aparte de que tiene un período de 2 ^ 31-2.En las macros SAS, las variables macro se referencian con un precedente
&
y se resuelven a sus valores en tiempo de ejecución.Como probablemente haya presenciado, SAS rara vez es un contendiente real en un concurso de golf de código .
fuente
Java, 193 bytes
Si bien esto no supera al líder actual de Java, decidí publicar de todos modos para mostrar un método diferente de cálculo. Es una versión de golf de OpenJDK's
nextGaussian()
.Con saltos de línea:
fuente
(s,n)->{java.util.Random r=new java.util.Random(s);for(float a,v;n-->0;System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))for(a=0;a>=1|a==0;a=v*v+(v=2*r.nextFloat()-1)*v)v=2*r.nextFloat()-1;}
T-SQL, 155 bytes
Use con EXEC RS, N porque no hay STD_IN en T-SQL donde S y N son la semilla y N respectivamente. S producirá secuencias "aleatorias" (RAND (semilla) es una implementación de números aleatorios realmente mala) cuando S> 2 ^ 16 (posiblemente antes de eso, pero no lo garantizo). Utiliza Box-Muller como la mayoría de las soluciones hasta ahora. 8388607 es 2 ^ 23-1, que con suerte debería generar 2 ^ 20 valores diferentes.
fuente
Powershell, 164 bytes
Igual que la mayoría de las respuestas con Box-Muller. No tiene mucha experiencia con Powershell, por lo que cualquier ayuda al golf sería apreciada.
fuente
Ruby, 72 bytes
Entrada (como función lambda):
Salida:
PD: Me gustaría saber si esto se puede jugar más. Solo soy un principiante.
fuente
Matlab, 77
La primera entrada debe ser
n
, la segundas
.fuente
Octava,
919688 bytesO, con espacios en blanco:
Establezca la semilla por adelantado y use el método Box-Mueller.
NB: Octave permite la generación de matrices de números aleatorios y puede usar operaciones estándar en estas matrices que producen salidas de matrices. El
.*
operador es la multiplicación elemento por elemento de dos matrices para producir el resultado.fuente
n(0,1)
yn(0,2)
obtienes primeros números diferentes, ¿verdad?Pyth, 32 bytes
No se está utilizando Python ahora en super comillas debido a las nuevas funciones que Pyth tiene ahora. Sin embargo, otro Box-Mueller.
Ese espacio al principio es importante.
La siembra no parece funcionar en el intérprete en línea, pero funciona bien en la versión local.El intérprete en línea parece estar arreglado, así que aquí hay un enlace permanente: enlace permanentefuente
.nZ
) que no se implementó cuando se hizo la pregunta. (En realidad se implementó hoy). Por lo tanto, esta respuesta no debe ser parte de la competencia ( meta.codegolf.stackexchange.com/questions/4867/… ).STATA, 85 bytes
Toma la entrada a través de la entrada estándar (el primer número es S, luego N). Establece la semilla en S. Establece el número de observaciones en N. Hace una variable y establece su valor en el valor de la transformación de Box Muller (gracias a @Alex por mostrarlo). Luego, enumera todas las observaciones en una tabla con el encabezado de columna a y los números de observación junto a ellas. Si no está bien, avíseme y puedo eliminar los encabezados y / o los números de observación.
fuente
R, 89 bytes
Sé que R se ha hecho antes, pero quería mostrar un enfoque diferente al Box-Muller que todos los demás usaron. Mi solución usa el Teorema del límite central .
fuente
a
en su código, de modo que el resultado sea "justo".)TI-Basic, 74 bytes
El
¹
es en realidad el operador inverso.fuente
Perl,
150108107 bytesEsto utiliza el método polar Marsaglia . Llamado con f (S, N).
Movió la asignación de
$a
en el cálculo de$c
.107:
Se eliminó el almacenamiento de números de repuesto y la definición de
$b
.108:
150:
fuente
Swift,
144142Nada inteligente, solo viendo cómo funciona Swift.
Esperaba poder usar (0 ... n) .map {} pero parece que el compilador no reconoce el mapa {} a menos que use un parámetro.
fuente
forEach
si no quieres un valor de retorno, y estoy bastante seguro de que_ in
es obligatorio/0xffffffff
por ciertoHaskell , 97 bytes
Pruébalo en línea!
Solo su transformación básica de Box-Muller, en una lista infinita de números aleatorios.
fuente
Python 3 , 118 bytes
Pruébalo en línea!
fuente
SmileBASIC, 81 bytes
Bueno, ahora que he respondido la primera pregunta, tengo que hacer todo el resto ...
La generación de números aleatorios es barato, pero la siembra de la RNG utiliza la más larga función incorporada en el lenguaje,
RANDOMIZE
.Quizás haya alguna forma de optimizar la fórmula. No veo cómo se requiere usar dos llamadas RNG.
fuente