Tâche
Étant donné un entier positif n
inférieur à celui 2^30
spécifié en entrée de la manière que vous choisissez, votre code doit générer un entier aléatoire entre 0
et n
inclus. Le nombre que vous générez doit être choisi de manière uniforme et aléatoire . C'est-à-dire que chaque valeur de 0
à n
doit se produire avec une probabilité égale (voir Règles et mises en garde).
Règles et mises en garde
Votre code peut supposer que tout générateur de nombres aléatoires intégré à votre langue ou bibliothèque standard qui prétend être uniformément aléatoire est en fait uniforme. Vous n'avez donc pas à vous soucier de la qualité de la source aléatoire que vous utilisez. cependant,
- Vous devez établir que si la source aléatoire que vous utilisez est uniforme, votre code génère correctement un entier aléatoire uniforme de
0
àn
. - Tout argument lors de l'appel d'une fonction aléatoire intégrée ou de bibliothèque doit être constant. Autrement dit, ils doivent être complètement indépendants de la valeur d'entrée.
- Votre code peut se terminer avec la probabilité 1 plutôt que d'être garanti de se terminer.
Remarques
randInt(0,n)
n'est pas valide car il prend l'entrée comme argument d'une fonction intégrée ou de bibliothèque.rand()%n
ne pas donner un nombre aléatoire uniforme en général. À titre d'exemple donné par betseg, siintmax == 15
etn = 10
, alors vous aurez beaucoup plus de chances d'obtenir0-5
que6-10
.floor(randomfloat()*(n+1))
ne donnera pas non plus un nombre aléatoire uniforme en général en raison du nombre fini de différentes valeurs possibles en virgule flottante entre 0 et 1.
code-golf
number
random
probability-theory
totalement humain
la source
la source
rng()
fournit0
-100
, sin = 75
et la fonction estrng()%75
, alors 0-25 sera plus courant ...)Réponses:
machines x86 avec
rdrand
instruction, 10 octetslangage machine
L'entrée est dans le registre
rdi
et la sortie dansrax
.Cela respecte l' ABI SYS V AMD64 afin que le code implémente efficacement une fonction C
avec des entiers 32 bits.
L'instruction
rdrand
est décrite par IntelEn traitant avec CSRNG, il est implicite que la distribution est uniforme, de toute façon, citant le NIST SP 800-90A:
La procédure génère un nombre aléatoire et s'il n'est pas strictement supérieur à l'entrée, il est renvoyé.
Sinon, le processus est réitéré.
Puisque
eax
est de 32 bits,rdrand
renvoie un nombre compris entre 0 et 2 32 -1, donc pour chaque n dans [0, 2 32 -1] le nombre d'itérations attendues est 2 32 / (n + 1) qui est défini pour tout n dans [0, 2 30 ).la source
jnc
sert?rdrand
définitCF
si les données retournées sont valides. Les données peuvent ne pas être valides car trop de requêtes ont vidé le pool d'entropie. Voir l'entrée manuelle pour rdrand et ceci .Gelée ,
76 octetsMerci à @JonathanAllan d'avoir joué au golf sur 1 octet!
Ne peut pas être exécuté sur TIO car (16!)! est un nombre énorme .
Comment ça marche
la source
Mathematica, 29 octets
Basé sur la réponse de Dennis Jelly .
Je ne recommanderais pas réellement de faire ça.
2e9!
est un assez grand nombre ...Il s'avère être le plus court pour générer un nombre énorme qui est divisible par toutes les entrées possibles et le mapper le résultat à la plage requise avec un simple modulo.
Échantillonnage de rejet, 34 octets
Mon ancienne approche qui a conduit à un code un peu plus intéressant:
Échantillonnage de rejet de base. Nous initialisons la sortie à 13! (qui est plus grand que l'entrée maximale 2 30 ), puis remplacez-le à plusieurs reprises par un entier aléatoire compris entre 0 et 13! tant que la valeur est supérieure à l'entrée.
la source
Brachylog , 9 octets
Essayez-le en ligne!
Cela utilise
13!
comme dans la réponse de Martin Ender (13ḟ
est un octet de moins que2^₃₀
).ṙ
est implémenté en utilisantrandom_between/3
, qui, lors du creusement de sa source, utiliserandom_float/0
ce qui est lié à celuirandom/1
qui utilise l'algorithme Mersenne Twister qui est uniforme pour nos besoins.Explication
la source
Prolog (SWI) , 38 octets
Fonctionne par échantillonnage de rejet.
Générez un nombre aléatoire compris entre 0 et 2 ^ 31-1 = 2147483647 jusqu'à ce qu'un autre inférieur ou égal à l'entrée soit trouvé.
Je sens que je devrais pouvoir utiliser une coupe au lieu de l’autre, mais je ne vois pas comment.
la source
repeat
, mais cela finit par être 3 octets de plus… Je ne sais pas s'il existe un moyen plus court d'avoir des points de choix infinis que de répéter.,!.
pour forcer un retour en arrière, mais soit je m'en souviens mal, soit ce n'est pas applicable à cette solution.Labyrinthe , 63 octets
(Merci à @MartinEnder pour son aide avec du golf lourd ici.)
Labyrinth est un langage 2D, et sa seule source d'aléatoire est dans une situation comme la suivante:
Supposons que le pointeur d'instruction se trouve sur
x
et se déplace vers le bas. Il atterrit ensuite sur le<
, qui si le haut de la pile est 0 (ce qui est toujours le cas dans le programme réel ci-dessus) décale la ligne actuelle de 1:Le pointeur d'instruction est maintenant sur le
<
déplace bas. À une jonction, Labyrinth tourne sur la base du haut de la pile - négatif est tourner à gauche, positif est tourner à droite et zéro est aller de l'avant. Si le haut de la pile est toujours nul à ce stade, nous ne pouvons pas avancer ou reculer car il n'y a pas de chemin, donc Labyrinth choisira au hasard entre tourner à gauche ou tourner à droite avec une probabilité égale.Essentiellement, le programme ci-dessus utilise la fonction aléatoire pour générer des nombres de 100 bits (100 spécifiés par
#00
ici) et continuer la boucle jusqu'à ce qu'il génère un nombre<= n
.Pour les tests, il sera probablement utile d'utiliser à la
#0"
place pour les nombres à 10 bits, le"
chemin étant sans opération.Essayez-le en ligne!Explication grossière:
la source
Python, 61 octets
Modifier: mis à jour pour éviter le formulaire interdit
Edit2: Enregistré 2 octets, merci @ JonathanAllan
Edit3: payé 2 octets pour une solution entièrement fonctionnelle - merci encore @JonathanAllan
Edit4: supprimé
f=
, économisant 2 octetsEdit5: enregistré 1 octet de plus grâce à @ JonathanAllan
Edit6: enregistré 2 octets de plus grâce à @ JonathanAllan
À ce moment-là, git blame me désignerait les mauvaises choses, et JonathanAllan pour les choses qui aident.
Edit7: Quand il pleut, il déverse - encore 2 octets
Edit8: Et encore 2 octets
la source
n
, mais vous pouvez enregistrer deux octets lorsque vous corrigez cela en utilisantfrom random import*
et en supprimant ler.
....*(-~n*1.0/2**30))
plutôt que...*((n+1)*1.0/2**30))
randrange
semble accepter un flotteur, donclambda n,x=2.**30:int(randrange(x)*-~n/x)
enregistre deux autres [modifier ...] quatre!Python 2 , 61 octets
Pseudo-aléatoirement choisit des entiers entre 0 et k pour toutes les valeurs de k entre 0 et 2 31 - 2 , puis prend l'entier correspondant à k = n .
la source
Lot, 64 octets
%random%
ne donne que 15 bits de hasard, donc je dois combiner deux nombres aléatoires. Boucles jusqu'à ce que la valeur aléatoire se situe dans la plage souhaitée, donc lente pour faiblen
; 98 octets pour une version plus rapide:la source
n
?call
, l'appel d'un script batch met fin au script actuel.MATL , 12 octets
Merci à @AdmBorkBork et à @Suever de m'avoir expliqué comment désactiver le cache TIO.
Essayez-le en ligne! .
Cela utilise une méthode de rejet : générer un entier aléatoire de
0
à2^30-1
et répéter tant qu'il dépasse l'entréen
. Il est garanti que cela se terminera avec probabilité1
, mais le nombre moyen d'itérations est2^30/n
, et cela prend donc très longtemps pourn
beaucoup plus petit que2^30
.la source
JavaScript (ES6),
5554 octetsGénère des entiers dans la plage [0 ... 2 k - 1] , où k est le plus petit entier tel que 2 k est supérieur à n . Se répète jusqu'à ce que le résultat tombe [0 ... n] .
Pourquoi?
Ceci est basé sur les hypothèses suivantes:
En interne, les valeurs entières pseudo-aléatoires générées par le moteur JS à alimenter
Math.random()
sont uniformes sur n'importe quel intervalle [0 ... 2 k -1] (avec k <32 ).Une fois multipliées par une puissance exacte de 2, les valeurs flottantes IEEE 754 renvoyées par
Math.random()
sont toujours uniformes sur de tels intervalles.Si quelqu'un peut confirmer ou réfuter ces hypothèses, faites-le moi savoir dans les commentaires.
Démo
Génère 1 million de valeurs dans [0 ... 2] et affiche les statistiques de résultat.
Afficher l'extrait de code
la source
Bash (+ coreutils), 44 octets
/ dev / urandom based solution
Lit les entiers 32 bits non signés
/dev/urandom
et les filtreawk
jusqu'à ce qu'il en trouve un dans une plage donnée, puissed q
abandonne le canal.la source
Haskell, 70 octets
Pas un algorithme très efficace mais ça marche. Il génère une liste infinie d'entiers (ou flotte si nécessaire, en raison du système de type de Haskell) délimité par [0,2 ^ 30] et prend le premier inférieur ou égal à n. Pour les petits n, cela peut prendre beaucoup de temps. Les nombres aléatoires doivent être uniformément répartis, comme spécifié dans la documentation de randomR afin que tous les nombres de l'intervalle [0,2 ^ 30] aient la même probabilité (1 / (2 ^ 30 + 1)) donc tous les nombres de [ 0, n] ont la même probabilité.
Version alternative:
Cette version est terrible mais elle enregistre un octet entier.
randoms
utilise une plage arbitraire définie par le type pour générer une liste infinie de nombres. Cela peut inclure des négatifs, nous devons donc les mapper avecabs
pour les forcer positifs (ou zéro). C'est extrêmement lent pour toutes les valeurs de n qui ne sont pas absurdement grandes. EDIT : J'ai réalisé plus tard que cette version n'est pas uniformément distribuée car la probabilité d'obtenir 0 est pire que les autres nombres en raison de l'utilisation deabs
. Pour produire un certain nombre,m
le générateur pourrait produirem
ou,-m
mais dans le cas de 0, seul 0 fonctionnera, donc sa probabilité est la moitié des autres nombres.la source
Gelée , 9 octets
Essayez-le en ligne! - le code ci-dessus ne fonctionnera pas sur TIO depuis une plage de taille 16! doivent être construits en premier (sans parler du fait qu'ils doivent ensuite être mélangés puis filtrés!), c'est donc la même chose à une échelle beaucoup plus petite, répétée 30 fois pour une entrée de 3 avec une limite de 10.
Comment?
Remarque: il serait plus d'un millier de fois plus efficace pour le même nombre d'octets de
ȷ⁵
faire ce à quoi on s'attendrait naïvement et de retourner de dix à dix, mais ce n'est pas le cas car le⁵
n'est pas évalué comme un dix littéral à utiliser par le nombre littéral,ȷ...
mais plutôt deux littéraux distincts sont analysés,ȷ
avec son exposant par défaut de trois donnant mille et⁵
dix.la source
JDK 9 sur jshell,
7559 octetsUsage
OptionalInt
. Les règles ne spécifient pas que le type de retour doit être une primitive et je considère anOptionalInt
comme une représentation valide du résultat.la source
Optional
est acceptée. Je confirmerais avec l'affiche si j'étais vous. De plus, pas besoin de compter toute la mission; seule l'expression lambda est suffisante.n
etnew Random()
.PHP, 30 octets
Courez avec
echo <N> | php -Rn '<code>'
.choisit un nombre aléatoire entre 0 et
getrandmax()
(2 ** 31-1 sur ma machine 64 bits);se répète alors que c'est plus grand que l'entrée.
Cela peut prendre un certain temps ... mon AMD C-50 (1 GHz) a nécessité entre 0,3 et 130 secondes
N=15
.Un moyen plus rapide pour la moyenne
N
( 46 octets ):ou
prend
N+1
des entiers aléatoires, les résume et prend le modulo avecN+1
.Le C-50 a besoin d'env. 8 secondes pour 1 million d'exécutions.
Une solution invalide pour 19 octets :
la source
PowerShell , 35 octets
Essayez-le en ligne!
Une autre méthode d'échantillonnage de rejet. Il s'agit d'une
for
boucle infinie , définissant la valeur de$a
pour être unRandom
entier entre0
et1gb
(= 1073741824 = 2^30
), et continue de boucler tant que cet entier est-g
ramené àt
l'entrée$args
. Une fois la boucle terminée, nous mettons simplement$a
le pipeline et la sortie est implicite.Remarque: cela prendra beaucoup de temps si l'entrée est un petit nombre.
la source
Python 2 ,
7269 octets-3 octets grâce à xnor (remplacer le
id
intégré en tant que variable)Essayez-le en ligne!
randrange(2**30)
produit un nombre pseudo-uniformément distribué (Mersenne Twister 2 19937-1 ) à partir de la plage [0,2 30 ) . Puisqu'iln
est garanti d'être inférieur à 2 30, il peut simplement être appelé à plusieurs reprises jusqu'à ce qu'il ne soit pas supérieur à l'entrée. Cela prendra beaucoup de temps pour des valeurs très bassesn
, mais fonctionne généralement dans la minute même pour des entrées aussi faibles que 50.la source
r=''
comme "infini". Ou, mieux encore, n'initialisez pasr
et utilisez plutôtid
partout pourr
.Perl 6 , 29 octets
Inspiré de la solution Mathematica de Martin Ender .
Génère une séquence infinie paresseuse d'entiers aléatoires entre 0 et 2 ^ 30-1, et prend le premier compris entre 0 et l'entrée.
Essayez-le en ligne!
la source
05AB1E , 11 octets
Essayez-le en ligne!
Explication
Comme la liste
[0 ... 2147483648]
est trop grande pour TIO, le lien utilise à la1.000.000
place.Solution alternative (en moyenne) beaucoup plus rapide de 11 octets
Essayez-le en ligne
Explication
la source
žJL.R%
pour 6 à moins que je manque quelque chose d'énorme. Appuyez sur 2 ^ 32, liste de 0 à 2 ^ 32, sélection aléatoire. Entrée Modulo. Va absolument vider l'efficacité que vous avez.I
in there for 7 bytes to get the arguments for modulus in the right order (and maybeÝ
instead ofL
), but otherwise that's certainly a shorter solution. I saw Dennis doing that in his Jelly answer, but as this was my first idea I kept this. As that approach is different from this you could post it as a separate answer.DI‹Ï
would avoid the loop.0
entraînerait presque toujours une boucle presque infinie, ce qui rend difficile la terminaison. Bien que la solution permette la possibilité de se terminer dans tous les scénarios, elle n'est pas garantie en raison du caractère aléatoire.Python 2, 89 octets
Explication
C’est très inefficient, as it creates 2^31 integers, shuffles and filters them.
Je ne vois aucun intérêt à partager un lien TIO, où il crée de si grandes listes, alors voici un lien TIO pour
n
= 100.Essayez-le en ligne!
la source
Java 8,
8483807162 bytes-1 byte thanks to @OliverGrégoire.
-3 bytes thanks to @Jakob.
-9 bytes converting Java 7 to Java 8.
-9 bytes by changing
java.util.Random().nextInt(1<<30)
to(int)(Math.random()*(1<<30))
.Explanation:
Try it here.
NOTE: May obviously take very long for small inputs.
Example output:
la source
2^30
=1073741824
. You preferred to use-1>>>1
(=2147483647
). But this exists:1<<30
which is exactly equals to2^30
; and is 1 byte shorter.int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}
?Math.random()
instead ofjava.util.Random().nextInt
.Python 3, 51 bytes
Here is a python solution with an unorthodox random source.
Try it online!
So to break this down.
Gets the input number, and adds
1
to it.Creates the set
{0, 1, 2, 3, 4, ... n}
for all possible results.Takes the set, converts it to list, and grabs the first item.
This works because in Python 3, the order of
set()
is established by PYTHONHASHSEED (can't be obtained but is established on script execution).Admittedly, I am guessing that this is a uniform distribution, as the
hash()
value is randomly assigned and I am looking at randomly picking the value with a specifichash()
, rather then just returning thehash(input())
itself.If anyone knows whether this is a uniform distribution, or how I could test that, please comment.
la source
C#, 57 bytes
Anonymous function which returns an integer between 0 and n inclusive.
The smaller the input number, the longer the time to return a random value.
Full program:
la source
Next
is not static.Bash + coreutils, 20 bytes
Golfed
seq 0 $1|shuf|sed 1q
Shuf will use the following code: to generate permutations:
which ends up in
randint_genmax
which, in turn, will read a few bytes of the random data from the low-level source of randomness:
i.e. at the low-level, there is no direct dependency between the
shuf
input value and the data read from the source of randomness (aside from computing the required byte buffer capacity).la source
jot will arrange for all the values in the range to appear in the output with an equal probability
(that's probably borderline, but still).SmileBASIC, 38 bytes
Generates random numbers until it gets one that is smaller than the input.
la source
Ruby,
23 15 23 3229 bytesHow it works:
1while [...];
executes the statement at least once:1
beforewhile
acts as a nopla source
Ohm, 26 bytes
Explanation:
la source
Go,
6361 bytesUse it like this:
Test it live at the go playground
la source
Golang,
847871 bytesSimple rejection sampling.
Note: since the math/rand seed is a constant 1, the caller must seed unless a constant result is desired.
Test: https://play.golang.org/p/FBB4LKXo1rNo longer practically testable on a 64-bit system, since it's returning 64-bit randomness and using rejection testing.la source
import."math/rand"
thenInt31
is available in the global namespace and you can save 4 bytes, alsoint
is guaranteed to be at least 32 bits, saving you another 6 bytes:=
syntax for another 3 bytesInt()
function in the rand package, also, you can remove the space afterimport