Su tarea es escribir un programa o una función que genere n
números aleatorios del intervalo [0,1] con una suma fija s
.
Entrada
n, n≥1
, número de números aleatorios para generar
s, s>=0, s<=n
, suma de números a generar
Salida
Una n
tupla aleatoria de números de coma flotante con todos los elementos del intervalo [0,1] y la suma de todos los elementos iguales a s
, salida de cualquier manera conveniente y sin ambigüedades. Todas las n
tuplas válidas tienen que ser igualmente probables dentro de las limitaciones de los números de coma flotante.
Esto es igual al muestreo uniforme desde la intersección de los puntos dentro del n
cubo de la unidad dimensional y el n-1
hiperplano dimensional que atraviesa (s/n, s/n, …, s/n)
y es perpendicular al vector (1, 1, …, 1)
(ver el área roja en la Figura 1 para ver tres ejemplos).
Figura 1: El plano de salidas válidas con n = 3 y sumas 0.75, 1.75 y 2.75
Ejemplos
n=1, s=0.8 → [0.8]
n=3, s=3.0 → [1.0, 1.0, 1.0]
n=2, s=0.0 → [0.0, 0.0]
n=4, s=2.0 → [0.2509075946818119, 0.14887693388076845, 0.9449661625992032, 0.6552493088382167]
n=10, s=9.999999999999 → [0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999]
Reglas
- Su programa debería terminar en menos de un segundo en su máquina al menos con
n≤10
y cualquier s válido. - Si lo desea, su programa puede ser exclusivo en el extremo superior, es decir,
s<n
y los números de salida del intervalo medio abierto [0,1] (rompiendo el segundo ejemplo) - Si su idioma no admite números de coma flotante, puede falsificar la salida con al menos diez dígitos decimales después del punto decimal.
- Las lagunas estándar no están permitidas y se permiten métodos de entrada / salida estándar.
- Este es el código de golf , por lo que gana la entrada más corta, medida en bytes.
This is equal to uniformly sampling from the intersection
: puedo ver un programa que elige al azar solo desde las esquinas de esa intersección. ¿Sería eso válido?s==0 or s==3
. Para todos los demás valores des
, el plano tiene un área distinta de cero y tiene que elegir de manera uniforme y aleatoria un punto en ese plano.s=2.99999999999, n=3
? ¿Podemos generar reales aleatorios en múltiplos de, digamos1e-9
,?Respuestas:
Wolfram Language (Mathematica) ,
9290 bytesPruébalo en línea!
Código sin golf:
Aquí hay una solución que funciona en 55 bytes, pero por ahora (la versión 12 de Mathematica) está restringida a
n=1,2,3
porque seRandomPoint
niega a dibujar puntos de hiperplanos de dimensiones superiores (en la versión 11.3 de TIO también fallan=1
). Sinn
embargo, puede funcionar para más alto en el futuro:Pruébalo en línea!
Código sin golf:
fuente
JavaScript (Node.js) ,
122115bytesPruébalo en línea!
fuente
Python 2 ,
144128119 bytesPruébalo en línea!
fuente
g(4, 2.0)
1,000 veces para obtener 4,000 puntos y los resultados se ven así, lo que parece bastante uniforme.Java 8,
194188196237236 bytes+49 bytes (188 → 196 y 196 → 237) para corregir la velocidad de los casos de prueba que se acercan a 1, así como también arreglar el algoritmo en general.
Pruébalo en línea
Explicación:
Usa el enfoque de esta respuesta Stackoverflow , dentro de un bucle, siempre y cuando uno de los elementos es aún mayor que 1.
Además, si
2*s>n
,s
será transformado enn-s
, y se establece un indicador para indicar que debemos utilizar1-diff
en lugar dediff
en el resultado de matriz (gracias por el consejo @soktinpk y @ l4m2 ).fuente
test(10, 9.99);
10, 9.0
justo después de editar para corregir eln=10, s=9.999999999999
caso de prueba. No estoy seguro de si hay una solución en Java mientras aún mantiene su aleatoriedad uniforme. Tendré que pensarlo por un tiempo. Por ahora lo editaré para indicar que se agota el tiempo de espera.n-s<1
puede llamarf(n,n-s)
y voltear cada número1/2
(es decir, reemplazarx
con1-x
) como lo hizo l4m2. Esto podría resolver el problema de los númeross
cercanosn
.s+s>n
lugar den-s<1
, pero cuando miré las otras respuestas de JavaScript, realmente tenía sentido. Todo está arreglado ahora, incluido otro error que todavía estaba presente. Los bytes subieron bastante, pero todo funciona ahora. Trabajará el byte-cuenta atrás desde aquí. :)JavaScript (Node.js) , 153 bytes
Pruébalo en línea!
fuente
C ++ 11,
284267 bytes-17 bytes gracias a
la biblioteca aleatoria Zacharý Utiliza C ++, salida en la salida estándar
Para llamar, solo necesita hacer eso:
Donde el parámetro de plantilla (aquí, 2) es N, y el parámetro real (aquí, 0.0) es S
fuente
<z>
yu
typedef float z;template<int N>void g(z s){z a[N],d=s/N;int i=N;for(;i;)a[--i]=d;std::uniform_real_distribution<z>u(.0,d<.5?d:1-d);std::default_random_engine e;for(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}for(;i;)std::cout<<a[--i]<<' ';}
. Una nueva línea no tiene que ser el separador entre elementosd
completo cambiandod=s/N
as/=N
Sugerir volver a trabajar el segundo ciclo enfor(z c;i<N;a[++i%N]-=c)a[i]+=c=u(e);
lugar defor(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}
(tenga%N
en cuenta lo agregado para que el programa calcule el primer número correctamente)Limpio ,
221201 bytesLimpio, código de golf o números aleatorios. Elige dos.
Pruébalo en línea!
Función parcial literal
:: (Int Real -> [Real])
. Solo producirá nuevos resultados una vez por segundo.Preciso hasta al menos 10 decimales.
fuente
R , 99 bytes (con
gtools
paquete)Pruébalo en línea!
fuente
C,
132127125118110107 bytes-2 bytes gracias a @ceilingcat
Pruébalo en línea!
fuente
[0,1]
, y su distribución conjunta no es uniforme.n=4
, los valoress=3.23
y lass=0.89
salidas están fuera del rango. Más concretamente, la distribución deX-s/n
debería depender des
, pero no lo hace.Haskell ,
122217208 bytesPruébalo en línea!
A veces las respuestas están ligeramente desviadas debido, supongo, a un error de coma flotante. Si es un problema, puedo solucionarlo a un costo de 1 byte. Tampoco estoy seguro de qué tan uniforme es esto (bastante seguro de que está bien, pero no soy tan bueno en este tipo de cosas), así que describiré mi algoritmo.
La idea básica es generar un número,
x
luego restarlos
y repetirlo hasta que tengamosn
elementos y luego mezclarlos. Generox
con un límite superior de 1 os
(el que sea menor) y un límite inferior des-n+1
o 0 (el mayor). Ese límite inferior está ahí, de modo que en la próxima iteracións
seguirá siendo menor o igual quen
(derivación:s-x<=n-1
->s<=n-1+x
->s-(n-1)<=x
->s-n+1<=x
).EDITAR: Gracias a @ michi7x7 por señalar una falla en mi uniformidad. Creo que lo solucioné con barajar pero avíseme si hay otro problema
EDIT2: recuento de bytes mejorado más restricción de tipo fijo
fuente
Haskell , 188 bytes
Sin golf:
Pruébalo en línea!
fuente