Le défi
Écrivez un programme ou une fonction qui ne prend aucune entrée et génère un vecteur de longueur dans une direction aléatoire théoriquement uniforme .
Cela équivaut à un point aléatoire sur la sphère décrit par
résultant en une distribution comme celle-ci
Sortie
Trois flotteurs d'une distribution aléatoire théoriquement uniforme pour laquelle l'équation est fidèle aux limites de précision.
Remarques du challenge
- La distribution aléatoire doit être théoriquement uniforme . Autrement dit, si le générateur de nombres pseudo-aléatoires devait être remplacé par un vrai RNG à partir des nombres réels, il en résulterait une distribution aléatoire uniforme des points sur la sphère.
- Générer trois nombres aléatoires à partir d'une distribution uniforme et les normaliser n'est pas valide: il y aura un biais vers les coins de l'espace tridimensionnel.
- De même, générer deux nombres aléatoires à partir d'une distribution uniforme et les utiliser comme coordonnées sphériques n'est pas valide: il y aura un biais vers les pôles de la sphère.
- Une bonne uniformité peut être obtenue par des algorithmes comprenant, mais sans s'y limiter:
- Générez trois nombres aléatoires , et partir d'une distribution normale (gaussienne) autour de et normalisez-les.
- Générez trois nombres aléatoires , et partir d'une distribution uniforme dans la plage . Calculez la longueur du vecteur par . Ensuite, si, rejetez le vecteur et générez un nouvel ensemble de nombres. Sinon, si, normalisez le vecteur et retournez le résultat.
- Générez deux nombres aléatoires et partir d'une distribution uniforme dans la plage et convertissez-les en coordonnées sphériques comme suit: pour que,etpuissent être calculés par
- Fournissez dans votre réponse une brève description de l'algorithme que vous utilisez.
- En savoir plus sur la sélection de points de sphère sur MathWorld .
Exemples de sortie
[ 0.72422852 -0.58643067 0.36275628]
[-0.79158628 -0.17595886 0.58517488]
[-0.16428481 -0.90804027 0.38532243]
[ 0.61238768 0.75123833 -0.24621596]
[-0.81111161 -0.46269121 0.35779156]
Remarques générales
- C'est du code-golf , donc la réponse utilisant le moins d'octets dans chaque langue gagne.
- Règles standard , les règles d' E / S et les règles échappatoire applicables.
- Veuillez inclure un lien Essayez-le en ligne ou équivalent pour montrer que votre code fonctionne.
- S'il vous plaît motiver votre réponse avec une explication de votre code.
pi/6 ≈ 0.5236
de produire une sortie. C'est l'aire de la sphère inscrite dans le cube unité-surfaceRéponses:
Wolfram Language (Mathematica) , 20 octets
Essayez-le en ligne!
Est-ce exactement ce qu'il dit sur l'étain.
la source
R , 23 octets
Essayez-le en ligne!
Génère 3 réalisations de la distributionN(0,1) et normalise le vecteur résultant.
Parcelle de 1000 réalisations:
la source
Code machine x86-64 -
63 62 5549 octetsUtilise le deuxième algorithme, modifié. Renvoie le vecteur de
[x, y, z, 0]
dans xmm0.Explication:
Pousse la valeur de 1 et 2 ^ 31 en tant que flottant à la pile. Les données se chevauchent en raison de l'extension de signe, économisant quelques octets.
vbroadcastss xmm1,dword ptr [rsp+5]
Charge la valeur de 2 ^ 31 dans 4 positions de xmm1.Génère un entier 32 bits aléatoire et le charge au bas de xmm0.
Génère un entier aléatoire de 32 bits, le convertit en float (signé) et divise par 2 ^ 31 pour obtenir des nombres entre -1 et 1.
vdpps xmm2,xmm0,xmm0,7Fh
ajoute les carrés des 3 flotteurs inférieurs en utilisant lui-même un produit scalaire, masquant le flotteur supérieur. Cela donne la longueurCompare la longueur au carré avec 1 et rejette les valeurs si elle n'est pas égale à 1. Si la longueur au carré est un, alors la longueur est également un. Cela signifie que le vecteur est déjà normalisé et enregistre une racine carrée et divise.
Restaurez la pile.
ret
renvoie la valeur en xmm0Essayez-le en ligne .
la source
aesenc
pour produire 128 bits "aléatoires" est tout simplement magnifique.Python 2 , 86 octets
Essayez-le en ligne!
Génère uniformément la coordonnée z de -1 à 1. Ensuite, les coordonnées x et y sont échantillonnées uniformément sur un cercle de rayon
(1-z*z)**.5
.Il n'est peut-être pas évident que la distribution sphérique soit en facteur uniforme sur la coordonnée z (et donc sur chaque coordonnée). C'est quelque chose de spécial pour la dimension 3. Voyez cette preuve que la surface d'une tranche horizontale d'une sphère est proportionnelle à sa hauteur. Bien que les tranches près de l'équateur aient un rayon plus grand, les tranches près du pôle sont plus orientées vers l'intérieur et il s'avère que ces deux effets s'annulent exactement.
Pour générer un angle aléatoire sur ce cercle, nous élevons l'unité imaginaire
1j
à une puissance uniformément aléatoire entre 0 et 4, ce qui nous évite d'avoir besoin de fonctions trigonométriques, pi ou e, dont chacune aurait besoin d'une importation. Nous extrayons ensuite la partie réelle imaginaire. Si nous pouvons sortir un nombre complexe pour deux des coordonnées, la dernière ligne pourrait êtreprint a,z
.86 octets
Essayez-le en ligne!
Génère trois normales et met le résultat à l'échelle.
Python 2 avec numpy, 57 octets
Essayez-le en ligne!
sum(a*a)**.5
est plus court quelinalg.norm(a)
. On pourrait aussi fairedot(a,a)
pour la même durée quesum(a*a)
. En Python 3, cela peut être raccourci ena@a
utilisant le nouvel opérateur@
.la source
z
, à partir d'une distribution uniforme, n'est pas modifié.z
, et je l'ai corrigé pour quelques octets.Octave ,
40 3322 octetsNous échantillonnons une distribution normale standard 3D et normalisons le vecteur:
Essayez-le en ligne!
la source
disp
:)Unity C # , 34 octets
Unity a une fonction intégrée pour les valeurs aléatoires de la sphère unitaire, j'ai donc pensé la publier.
la source
f=>Random.onUnitSphere
f
le type de; l'utilisationvar
ne fonctionne qu'à l'intérieur d'une méthode etSystem.Func<Vector3>
était plus longue.f=>Random.onUnitSphere
est une soumission parfaitement valablef=>UnityEngine.Random.onUnitSphere
vous sauve leusing
MATL , 10 octets
Essayez-le en ligne!
Explication
Cela utilise la première approche décrite dans le défi.
la source
Rubis ,
34 5049 octetsEssayez-le en ligne!
Renvoie un tableau de 3 nombres
[z,y,x]
.x
ety
sont générés en augmentanti
(racine carrée de -1) à une puissance aléatoire entre 0 et 4. Ce nombre complexe doit être mis à l'échelle de manière appropriée en fonction de laz
valeur conformément au théorème de Pythagore:(x**2 + y**2) + z**2 = 1.
La
z
coordonnée (qui est générée en premier) est simplement un nombre uniformément réparti entre -1 et 1. Bien que cela ne soit pas immédiatement évident, dA / dz pour une tranche à travers une sphère est constant (et égal au périmètre d'un cercle de même rayon que toute la sphère.).Cela a apparemment été découvert par Archimède qui l'a décrit d'une manière très peu semblable au calcul, et il est connu sous le nom de théorème d'Archimède Hat-Box. Voir https://brilliant.org/wiki/surface-area-sphere/
Une autre référence des commentaires sur la réponse de xnor. Une URL étonnamment courte, décrivant une formule étonnamment simple: http://mathworld.wolfram.com/Zone.html
la source
[z, x+yi]
Je vais le laisser tel quel, sauf si vous dites que c'est OK.z*z
place dez**2
?z*z
. Je l'ai édité maintenant. L'autre chose que je pourrais faire est de remplacerrand*4
par quelque chose commez*99
oux*9E9
(limitant effectivement les valeurs possibles à une spirale très fine sur la sphère) mais je pense que cela réduit la qualité du hasard.05AB1E ,
2322 octetsImplémente le 2ème algorithme.
Essayez-le en ligne ou obtenez quelques sorties aléatoires supplémentaires .
Explication:
REMARQUE: 05AB1E n'a pas de fonction intégrée pour obtenir une valeur décimale aléatoire dans la plage . Au lieu de cela, je crée une liste par incréments de et je choisis des valeurs aléatoires dans cette liste. Cette augmentation pourrait être modifiée pour en changeant le pour dans le code (bien qu'il deviendrait plutôt lent ..).[0,1) 0.00001 0.000000001
5
9
la source
TI-BASIC, 15 octets *
En utilisant l'algorithme "générer 3 valeurs normalement distribuées et normaliser ce vecteur".
La fin d'un programme avec une expression imprime automatiquement le résultat sur l'écran d'accueil une fois le programme terminé, de sorte que le résultat est réellement affiché, pas seulement généré et noirci.
*:
randNorm(
est un jeton de deux octets , les autres sont des jetons d'un octet . J'ai compté l'initiale (inévitable):
, sans que ce soit 14 octets. Enregistré en tant que programme avec un nom à une lettre, il prend 24 octets de mémoire, ce qui inclut les 9 octets de surcharge du système de fichiers.la source
JavaScript (ES7),
77 7675 octetsImplémente le 3 ème algorithme, en utilisant .sin(ϕ)=sin(cos−1(z))=1−z2−−−−−√
Essayez-le en ligne!
Commenté
JavaScript (ES6), 79 octets
Implémente le 2 ème algorithme.
Essayez-le en ligne!
Commenté
la source
Traitement de 26 octets
Programme complet
Il s'agit de la mise en œuvre https://github.com/processing/processing/blob/master/core/src/processing/core/PVector.java
la source
Python 2 , 86 octets
Essayez-le en ligne!
Implémente le premier algorithme.
Python 2 ,
107103 octetsEssayez-le en ligne!
Implémente le deuxième algorithme.
la source
Haskell ,
125123119118 octetsEssayez-le en ligne!
Fait trois uniformes aléatoires et échantillonnage de rejet.
la source
JavaScript, 95 octets
Vous
n'avez pasbesoin de ne pas entrera
.la source
Julia 1.0 , 24 octets
Essayez-le en ligne!
Dessine un vecteur de 3 valeurs, tiré d'une distribution normale autour de 0 avec l'écart-type 1. Il suffit ensuite de les normaliser.
la source
randn()
, à partir de quelques tests rapides, ne semble pas lié à la plage requise. En outre, cela n'inclut pas une vérification pourhypot()
renvoyer une valeur>1
, qui doit être rejetée.randn
simuler à partir d'une distribution normale standard plutôt que d'une distribution uniforme (0,1), donc cette approche est identique à celle de R.[-1,1)
division par eux par le hypoténuse, qui sera>1
, compense cela? Cela m'amène à me demander si le ternaire dans ma solution est nécessaire ...MathGolf ,
211918 octetsImplémentation du 2ème algorithme.
Essayez-le en ligne ou voyez quelques sorties supplémentaires en même temps .
Explication:
la source
Java 8 ( 3e algorithme modifié @Arnauld ),
131126119111 111109 octetsPort de la réponse JavaScript de @Arnauld , alors assurez-vous de voter pour lui!
-2 octets grâce à @ OlivierGrégoire .
Ceci est implémenté comme:
Essayez-le en ligne.
Ancienne implémentation du 3ème algorithme (
131126119 octets):Mis en œuvre en tant que:
Essayez-le en ligne.
Explication:
Java 8 (2ème algorithme),
153143 octetsEssayez-le en ligne.
2ème algorithme:
la source
sqrt(1-k*k)
économise en fait plus d'octets en Java qu'en JS. :)M.sin
, 1xM.cos
et 1xM.acos
, votre approche utilise 2xM.sin
et 1xM.sqrt
, d'où proviennent principalement les octets enregistrés supplémentaires. :)double[]
car cela ne change pas le nombre d'octets.)Japt , 20 octets
Port d' implémentation d' Arnauld du 2ème algorithme.
Essaye-le
la source
Pyth , 24 octets
Essayez-le en ligne!
Utilise l'algorithme # 2
la source
OCaml ,
1109995 octetsEDIT: a réduit certains octets en insérant et , en remplaçant le premier par a , et en profitant de l'associativité des opérateurs pour éviter certaines parens .i j
let ... in
fun
()
Essayez-le en ligne
Solution originale:
Je définis d'abord:
La
Random.float
fonction d'OCaml inclut les limites. Ensuite,Ceci est très similaire à l'implémentation du 3ème exemple (avec et ) sauf que je choisis et dans des intervalles plus grands pour éviter la multiplication (avec 2) plus tard.ϕ=p θ=t − i j
la source
0
et1
directement comme coordonnées sphériques. Ceci est incorrect, comme le montrent les remarques 3 et 4, car vous vous retrouvez avec un biais vers les pôles de la sphère. Vous pouvez corriger cela en appliquant la méthode indiquée dans la remarque 4.