Vous disposez d'une fonction Rand5 (). Cette fonction renvoie des entiers parfaitement aléatoires (distribution égale) entre 1 et 5.
Fournissez la fonction Rand7 (), qui utilise Rand5 () pour produire des entiers parfaitement aléatoires entre 1 et 7.
code-challenge
math
random
Dan McGrath
la source
la source
Réponses:
Java - 61 caractères
Pilote de test pour validation:
Résultats
la source
rand5
. Je les ai calculés dans Maple en utilisant une algèbre matricielle simple, mais vous pouvez le faire avec un crayon et du papier en quelques minutes si vous le souhaitez. Quoi qu'il en soit, il s'avère qu'Omar a déjà publié les mêmes chiffres (sans facteur de normalisation) dans un commentaire à une autre réponse quelques jours plus tôt. (Aussi ps., Vous ne pouvez @notifier qu'un utilisateur par commentaire, bien que l'auteur du message soit toujours informé dans tous les cas.)Perl - 47 (au lieu de 52) caractères
De plus, j'arrive à utiliser l'opérateur ternaire ET la récursivité. Meilleur jour de ma vie!
OK, 47 caractères si vous utilisez mod au lieu de div:
la source
&
signes pour le ramener à 46 caractères (y compris l'espace, ce qui met votre version actuelle à 48).JavaScript, 42
Bonus ES5:
la source
Ruby - 54 caractères (basé sur la solution Dan McGrath, utilisant une boucle)
Ruby - 45 caractères (même solution, en utilisant la récursivité)
la source
(x=rand5+5*rand5-5)>7?
.En Python:
la source
En Common Lisp 70 caractères:
Les parenthèses prennent plus de place que je ne le souhaiterais.
la source
(defun rand7()(setq n(-(+(rand5)(* 5(rand5)))5))(if(> n 7)(rand7)n))
(defun rand7()(if(>(setq n(-(+(rand5)(* 5(rand5)))5))7)(rand7)n))
En c / c ++ en utilisant l' échantillonnage de rejet
62 caractères.
la source
while(x>7)
, de sorte que ne serait satisfaite que par des nombres dans la plage valide.Traduction en PHP, de la réponse publiée par Dan McGrath.
67 caractères.
la source
R, 34 caractères
En R (un langage construit pour le calcul statistique), une solution délibérément trompeuse:
Grâce à une évaluation paresseuse des arguments, j'ai supprimé le point-virgule et les accolades.
Sortie sur 10 ^ 6 répliques:
la source
Rand7=function(){r=Rand5();sample(7)[r]}
Rand7=function(){sample(7)[Rand5()]}
scala,
47, 4059 caractères:avec 2 entrées de rand5:
Je multiplie le premier-1 par 5 et j'ajoute le second. La plupart des résultats sont ignorés et conduisent à un nouveau calcul. Le résultat devrait être une distribution égale des valeurs de 1 à 25, dont je ne choisis que les 7 premières. Je pourrais accepter les 21 premiers avec la construction d'un modulo, mais cela conduirait à un code plus long.
code historique qui a échoué, mais pas très clairement. Merci à Ilmari Karonen de l'avoir signalé:
Merci à Yoshiteru Takeshita pour cette approche scala-2.8.0 qui a rendu la «somme» si facile. Ma solution avant:
rand5:
la source
def rand7=(1 to 7).map(_=>rand5).sum%7+1
C ++
C ++ (109)
Golfé
la source
Traduction en Javascript, de la réponse postée par Dan McGrath.
62 caractères
la source
function Rand7(){for(x=8;x>7;x=rand5()+5*rand5()-5);return x}
est un peu plus court: PJavaScript, 85
Je sais qu'il y a une réponse plus courte, mais je voulais montrer le test de ce puzzle. Il s'avère que seule la réponse de Clyde Lobo utilisant l'échantillonnage de rejet de Dan McGrath est correcte (entre les réponses JS).
la source
С ++
Distribution des nombres (1000000 entiers):
Le nombre moyen d'appels à Rand5 () pour chaque entier généré est d'environ 2,2 (2 à 10+).
la source
En Java (ou C / C ++ je suppose)
en utilisant la formule de génération d'Alexandru, en 65 caractères:
utilisant la formule de génération de Dan McGrath, en 60 caractères
la source
Clojure - 58 caractères
la source
Python,
5637 caractèresUne autre solution qui peut être erronée, en Python:
Cela semble trop simple, mais quand j'essaye:
J'obtiens une distribution raisonnablement uniforme (toutes entre 14000 et 14500).
D'accord, maintenant que quelqu'un a voté pour ce poste: cette solution est-elle vraiment correcte? J'ai plus posté ceci ici pour inciter les gens à le critiquer. Eh bien, si c'est correct, ma version golfée serait:
ce qui donne 37 caractères.
la source
Java, 65 caractères:
la source
Python, 70 caractères
mais complètement correct sur la base du raisonnement ici .
la source
Perl, 43 caractères, échantillonnage itératif de rejet
Cela donne un avertissement
Ambiguous use of -rand5 resolved as -&rand5()
, mais fonctionne correctement. L'ajout d'une&
seconde au deuxièmerand5
appel le corrige au prix d'un coup. (Inversement, l'autre&
peut également être supprimé s'ilrand5
a été défini avec un()
prototype.)Ps. La version suivante de 46 caractères est environ trois fois plus rapide:
la source
Java - 66 caractères
Plus longue que la routine précédente, mais je pense que celle-ci renvoie des nombres uniformément distribués en moins de temps.
la source
PostScript (46)
Cela utilise un codage de jeton binaire, par conséquent, voici un hexdump:
Pour l'essayer, vous pouvez également le télécharger .
Voici le code non golfé et commenté, ainsi que le code de test.
la source
la source
R (30 caractères)
Définissez rand7:
Parce que R a été écrit avec une analyse statistique à l'esprit, cette tâche est triviale, et j'utilise la fonction intégrée
sample
avec remplacement défini sur TRUE.Exemple de sortie:
la source
Sensationnel
exemple de distribution sur 35 000 itérations:
Est-ce mauvais que ce soit avec état?
la source
Mathematica, 30
la source
Que dis-tu de ça?
la source
/
opérateur fait-il des mathématiques entières? Qu'advient-il de vos résultats s'il utilise des mathématiques décimales, à virgule flottante ou entières?[2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25]
. Pas exactement uniforme.Java - 54
Test de distribution:
[1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]
Algorithme:
> Les nombres ne sont plus non corrélés entre eux, mais individuellement parfaitement aléatoires.
la source
Rubis (43 octets)
La solution de cemper93 portée sur Ruby est trois octets plus courte;) (34 octets)
la source
Code C / C ++ le code principal n'a qu'une seule ligne!
Le srand7 () est la graine de rand7, doit appeler cette fonction avant rand7, tout comme appeler srand avant rand en C.
C'est un très bon choix, car il n'appelle rand () qu'une seule fois, et aucune boucle, aucune dépense de mémoire supplémentaire.
Permettez-moi de l'expliquer: considérons un tableau entier de taille 5:
Nous avons donc obtenu le TABLEAU, chacun de 1-7 apparaît 5 fois dedans, et a tous les 35 nombres, donc la probabilité de chaque nombre est 5/35 = 1/7. Et la prochaine fois,
Après suffisamment de temps, nous pouvons obtenir la distribution uniforme de 1-7.
Ainsi, nous pouvons allouer un tableau pour restaurer les cinq éléments de 1-7 par boucle vers la gauche et obtenir un numéro du tableau à chaque fois par rand5. Au lieu de cela, nous pouvons générer les sept tableaux avant et les utiliser de manière circulaire. Le code est également simple, a de nombreux codes courts peuvent le faire.
Mais, nous pouvons utiliser les propriétés de l'opération%, donc le tableau 1-7 lignes est équivalent à (rand5 + i)% 7, c'est-à-dire: a = rand ()% 5 + 1 est rand5 en langage C, b = gi ++ % 7 génère toutes les permutations du tableau ci-dessus, et 0 - 6 remplace 1 - 7 c = (a + b)% 7 + 1, génère 1 - 7 uniformément. Enfin, nous avons obtenu ce code:
Mais, nous ne pouvons pas obtenir 6 et 7 au premier appel, nous avons donc besoin d'une graine, certains comme srand pour rand en C / C ++, pour perturber la permutation pour le premier appel formel.
Voici le code complet à tester:
la source
6
ou7
en l'appelant une fois ?int main(){if(rand7()==6) printf("Hello, world!");}
, l'approximation utilisant la boucle affichera 'Bonjour, monde!' 1 fois sur 7, mais pas votre code.