Entrée: deux entiers n et k donnés sous n'importe quelle forme qui convient à votre code
Sortie Une séquence aléatoire non décroissante de k entiers, chacun compris entre 1 et n. L'échantillon doit être choisi uniformément parmi toutes les séquences non décroissantes de k entiers avec des entiers compris entre 1 et n.
La sortie peut être dans n'importe quel format raisonnable qui vous convient.
Vous pouvez utiliser n'importe quel générateur pseudo-aléatoire fourni par votre bibliothèque / langue préférée.
On peut supposer que les entiers n, k> 0.
Exemple
Disons n, k = 2. Les séquences non décroissantes sont
1,1
1,2
2,2
Chaque séquence doit avoir une probabilité de 1/3 d'être sortie.
Restriction
Votre code ne devrait pas s'exécuter en quelques secondes pour k = 20 et n = 100.
Ce qui ne marche pas
Si vous échantillonnez simplement chaque entier au hasard dans la plage de 1 à n, puis triez la liste, vous n'obtiendrez pas une distribution uniforme.
la source
Réponses:
Réellement ,
1412 octetsCette réponse est basée sur la réponse de 05AB1E de Emigna et les réponses sur cette question Math.SE . Suggestions de golf bienvenues! Essayez-le en ligne!
Ungolfing
la source
Python, 89 octets
Générer une séquence croissante plutôt qu'une séquence non décroissante serait simple: il s'agit simplement d'un sous-ensemble aléatoire de
k
nombres entre1
etn
, triés.Mais, nous pouvons convertir une séquence croissante en une séquence non décroissante en réduisant chaque écart entre les nombres consécutifs de 1. Ainsi, un écart de 1 devient un écart de 0, ce qui rend des nombres égaux. Pour ce faire, diminuez la
i
'e valeur la plus élevée dei
Pour que le résultat soit de
1
àn
, l'entrée doit être de1
àn+k-1
. Cela donne une bijection entre des séquences de nombres non décroissants entre1
etn
, à des séquences croissantes entre1
etn+k-1
. La même bijection est utilisée dans l' argument étoiles et barres pour compter ces séquences.Le code utilise la fonction python
random.sample
, qui prend desk
échantillons sans remplacement dans la liste d'entrée. Le trier donne la séquence croissante.la source
import*
économiser 1 octet)05AB1E , 13 octets
Essayez-le en ligne!
Explication
la source
Python, 87 octets
La probabilité que la valeur maximale possible
n
soit incluse est égale àk/(n+k-1)
. Pour l'inclure, placez-le à la fin de la liste et décrémentez les nombres nécessaires restantsk
. Pour l'exclure, décrémentez la limite supérieuren
. Ensuite, répétez jusqu'à ce que plus aucune valeur ne soit nécessaire (k==0
).Python
random
ne semble pas avoir de fonction intégrée pour une variable de Bernoulli: 1 avec une certaine probabilité, et 0 sinon. Ainsi, cela vérifie si une valeur aléatoire entre 0 et 1 générée parrandom
tombe en dessousk/(n+k-1)
. Python 2 serait le rapport que la division du flotteur, de sorte que nous à la place multiplier par le dénominateur:k>random()*(n+k-1)
.la source
numpy.random
, ce qui est trop long.JavaScript (Firefox 30+), 74 octets
Explication
L'excellente réponse de Python de xnor contient un très bon résumé de la façon / pourquoi la technique utilisée ici fonctionne. La première étape consiste à créer la plage [1, 2, ..., n + k - 1] :
Ensuite, nous devons prendre k éléments aléatoires de cette plage. Pour ce faire, nous devons sélectionner chaque élément avec la probabilité s / q , où s est le nombre d'éléments encore nécessaires et q est le nombre d'éléments restant dans la plage. Puisque nous utilisons une compréhension de tableau, c'est assez simple:
Cela nous donne une séquence croissante de nombres uniformément répartis . Cela peut être corrigé en soustrayant le nombre d'éléments j que nous avons précédemment trouvé:
Enfin, en stockant k dans j , nous pouvons incorporer
k--
dans l'expression et économiser quelques octets:la source
TI-BASIC, 54 octets
Suivez la logique de xnor, avec une petite mise en garde. Nous pourrions théoriquement raser un octet en faisant quelque chose comme ceci:
Mais rand (est réservé pour créer une liste de nombres aléatoires, nous ne pourrions donc pas faire la multiplication implicite souhaitée pour enregistrer un octet.
Cela devrait fonctionner assez rapidement sur un 84+ selon la restriction, mais je vérifierai si je le peux.
la source
PHP,
777573 octetsCourez comme ceci:
Explication
Tweaks
end()
appel et défini$argv[2]
à la$k
place pour raccourcir l'accès aux arguments$i
chaque itération à la placela source