Votre tâche consiste à écrire un programme ou une fonction qui génère n
des nombres aléatoires de l'intervalle [0,1] avec une somme fixe s
.
Contribution
n, n≥1
, nombre de nombres aléatoires à générer
s, s>=0, s<=n
, somme des nombres à générer
Sortie
Un n
-tuple aléatoire de nombres à virgule flottante avec tous les éléments de l'intervalle [0,1] et la somme de tous les éléments égaux à s
, émis de toute manière pratique et sans ambiguïté. Tous les n
-tuples valides doivent être également probables dans les limites des nombres à virgule flottante.
Cela équivaut à un échantillonnage uniforme à partir de l'intersection des points à l'intérieur du n
cube d'unités dimensionnelles et de l' n-1
hyperplan dimensionnel qui traverse (s/n, s/n, …, s/n)
et est perpendiculaire au vecteur (1, 1, …, 1)
(voir la zone rouge sur la figure 1 pour trois exemples).
Figure 1: Le plan des sorties valides avec n = 3 et des sommes de 0,75, 1,75 et 2,75
Exemples
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]
Règles
- Votre programme doit se terminer en moins d'une seconde sur votre machine au moins avec
n≤10
et tout s valide. - Si vous le souhaitez, votre programme peut être exclusif sur l'extrémité supérieure, c'est-à
s<n
- dire et les numéros de sortie de l'intervalle semi-ouvert [0,1) (en cassant le deuxième exemple) - Si votre langue ne prend pas en charge les nombres à virgule flottante, vous pouvez simuler la sortie avec au moins dix chiffres décimaux après le point décimal.
- Les failles standard sont interdites et les méthodes d'entrée / sortie standard sont autorisées.
- Il s'agit de code-golf , donc l'entrée la plus courte, mesurée en octets, gagne.
This is equal to uniformly sampling from the intersection
- je peux voir un programme choisir aléatoirement à partir des coins de cette intersection. Serait-ce valable?s==0 or s==3
. Pour toutes les autres valeurs des
, le plan a une zone non nulle et vous devez choisir de manière uniforme et aléatoire un point sur ce plan.s=2.99999999999, n=3
? Pouvons-nous générer des réels aléatoires en multiples de, disons1e-9
?Réponses:
Wolfram Language (Mathematica) ,
9290 octetsEssayez-le en ligne!
Code non golfé:
Voici une solution qui fonctionne en 55 octets mais pour l'instant (Mathematica version 12) est limitée à
n=1,2,3
parce qu'elleRandomPoint
refuse de dessiner des points à partir d'hyperplans de dimension supérieure (dans la version 11.3 de TIO, elle échoue égalementn=1
). Cela peut fonctionner pour plusn
à l'avenir cependant:Essayez-le en ligne!
Code non golfé:
la source
JavaScript (Node.js) ,
122115 octetsEssayez-le en ligne!
la source
Python 2 ,
144128119 119 octetsEssayez-le en ligne!
la source
g(4, 2.0)
1 000 fois pour obtenir 4 000 points et les résultats ressemblent à ceci qui semble assez uniforme.Java 8,
194188 188196237236 octets+49 octets (188 → 196 et 196 → 237) pour fixer la vitesse des cas de test près de 1, ainsi que corriger l'algorithme en général.
Essayez-le en ligne
Explication:
Utilise l'approche de cette réponse StackoverFlow , dans une boucle tant que l'un des éléments est toujours plus grand que 1.
De plus, si
2*s>n
,s
sera changé enn-s
, et un indicateur est défini pour indiquer que nous devons utiliser à la1-diff
place dediff
dans le tableau de résultats (merci pour l'astuce @soktinpk et @ l4m2 ).la source
test(10, 9.99);
10, 9.0
juste après avoir édité pour corriger len=10, s=9.999999999999
cas de test .. Je ne sais pas s'il y a un correctif en Java tout en conservant son uniformité aléatoire .. Il faudra y penser pendant un certain temps. Pour l'instant, je vais le modifier pour qu'il expire.n-s<1
vous pouvez appelerf(n,n-s)
et retourner chaque numéro1/2
(c'est-à-dire le remplacerx
par1-x
) comme l4m2 l'a fait. Cela pourrait résoudre le problème des nombress
prochesn
.s+s>n
au lieu den-s<1
, mais quand j'ai regardé les autres réponses JavaScript, cela avait effectivement du sens. Tout est maintenant corrigé, y compris un autre bug qui était toujours présent. Les octets ont augmenté un peu, mais tout fonctionne maintenant. Fonctionnera le décompte d'octets à partir d'ici. :)JavaScript (Node.js) , 153 octets
Essayez-le en ligne!
la source
C ++ 11,
284267 octets-17 octets grâce à Zacharý
Utilise la bibliothèque aléatoire C ++, sortie sur la sortie standard
Pour appeler, il vous suffit de le faire:
Où le paramètre de modèle (ici, 2) est N, et le paramètre réel (ici, 0,0) est S
la source
<z>
etu
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]<<' ';}
. Une nouvelle ligne ne doit pas nécessairement être le séparateur entre les élémentsd
complètement en changeantd=s/N
ens/=N
Suggérez de retravailler la deuxième bouclefor(z c;i<N;a[++i%N]-=c)a[i]+=c=u(e);
au lieu defor(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}
(notez l'ajout%N
afin que le programme calcule correctement le premier nombre)Nettoyer ,
221201 octetsChiffres propres, codés au golf ou aléatoires. Choisis en deux.
Essayez-le en ligne!
Littéral de fonction partielle
:: (Int Real -> [Real])
. Ne produira de nouveaux résultats qu'une fois par seconde.Précisez jusqu'à au moins 10 décimales.
la source
R , 99 octets (avec
gtools
package)Essayez-le en ligne!
la source
C,
132127125118110 110107 octets-2 octets grâce à @ceilingcat
Essayez-le en ligne!
la source
[0,1]
, et leur distribution conjointe n'est pas uniforme.n=4
, les valeurss=3.23
ets=0.89
donne des sorties en dehors de la plage. Plus précisément, la distribution deX-s/n
devrait dépendres
, mais ce n'est pas le cas.Haskell ,
122217208 octetsEssayez-le en ligne!
Parfois, les réponses sont légèrement décalées en raison, je suppose, d'une erreur en virgule flottante. Si c'est un problème, je peux le résoudre au prix d'un octet. Je ne sais pas non plus à quel point c'est uniforme (je suis sûr que c'est bien mais je ne suis pas très bon dans ce genre de chose), donc je vais décrire mon algorithme.
L'idée de base est de générer un nombre,
x
puis de le soustraires
et de revenir jusqu'à ce que nous ayons desn
éléments, puis de les mélanger. Je génèrex
avec une limite supérieure de 1 ous
(la plus petite des deux) et une limite inférieure des-n+1
ou 0 (la plus grande des deux). Cette borne inférieure est là de sorte que lors de la prochaine itérations
sera toujours inférieure ou égale àn
(dérivation:s-x<=n-1
->s<=n-1+x
->s-(n-1)<=x
->s-n+1<=x
).EDIT: Merci à @ michi7x7 d'avoir signalé une faille dans mon uniformité. Je pense que je l'ai corrigé en mélangeant mais faites-moi savoir s'il y a un autre problème
EDIT2: nombre d'octets amélioré et restriction de type fixe
la source
Haskell , 188 octets
Ungolfed:
Essayez-le en ligne!
la source