Golf aléatoire du jour # 2: chiffres d'une distribution normale

12

À propos de la série

Tout d'abord, vous pouvez traiter cela comme n'importe quel autre défi de golf de code et y répondre sans vous soucier de la série. Cependant, il existe un classement pour tous les défis. Vous pouvez trouver le classement avec plus d'informations sur la série dans le premier post .

Bien que j'ai un tas d'idées alignées pour la série, les défis futurs ne sont pas encore gravés dans le marbre. Si vous avez des suggestions, faites-le moi savoir sur la publication sandbox correspondante .

Trou 2: nombres d'une distribution normale

Je ne peux pas croire que cela n'ait pas encore été fait! Vous devez générer des nombres aléatoires, à partir d'une distribution normale . Certaines règles (la plupart d'entre elles sont probablement couvertes automatiquement par la plupart des soumissions, mais certaines sont en place pour garantir la cohérence des résultats entre des langues très différentes):

  • Vous devez prendre deux entiers non négatifs en entrée : une valeur de départ Set le nombre Nde nombres à renvoyer. La sortie doit être une liste de Nnombres à virgule flottante, tirée d'une distribution normale avec une moyenne de 0 et une variance de 1 . Chaque fois que votre soumission reçoit la même graine, Selle doit produire le même nombre. En particulier, si elle est appelée une fois avec et une fois avec , les premières entrées des deux sorties doivent être identiques. De plus, au moins 2 16 valeurs différentes de devraient produire des séquences différentes.(S, N1)(S, N2)min(N1, N2)S

  • Vous pouvez utiliser n'importe quel générateur de nombres aléatoires intégré documenté pour tirer des nombres d'une distribution (approximativement) uniforme , à condition que vous puissiez le transmettre Set qu'il prenne en charge au moins 2 16 graines différentes. Si vous le faites, le RNG devrait être en mesure de renvoyer au moins 2 20 valeurs différentes pour tout nombre donné que vous lui demandez.

  • Si votre RNG uniforme disponible a une gamme plus petite, n'est pas semable ou prend en charge trop peu de graines, vous devez d'abord construire un RNG uniforme avec une gamme suffisamment large au-dessus de celui intégré ou vous devez implémenter votre propre RNG approprié en utilisant la graine. Cette page peut être utile pour cela.
  • Si vous n'implémentez pas d'algorithme établi pour générer des distributions normales, veuillez inclure une preuve d'exactitude. Dans les deux cas, l'algorithme que vous choisissez doit produire une distribution normale théoriquement exacte (sauf limitations des PRNG sous-jacents ou types de données à précision limitée).
  • Votre implémentation doit utiliser et renvoyer des nombres à virgule flottante (au moins 32 bits de large) ou des nombres à virgule fixe (au moins 24 bits de large) et toutes les opérations arithmétiques doivent utiliser la pleine largeur du type choisi.
  • Vous ne devez pas utiliser de fonctions intégrées directement liées à la distribution normale ou aux intégrales gaussiennes, comme la fonction d'erreur ou son inverse.

Vous pouvez écrire un programme complet ou une fonction et prendre une entrée via STDIN, un argument de ligne de commande, un argument de fonction ou une invite et produire une sortie via une valeur de retour ou en imprimant vers STDOUT (ou l'alternative la plus proche).

Set Nseront des entiers non négatifs, chacun inférieur à 2 20 . La sortie peut être dans n'importe quelle liste ou format de chaîne pratique et sans ambiguïté.

Il s'agit du code golf, donc la soumission la plus courte (en octets) l'emporte. Et bien sûr, la soumission la plus courte par utilisateur entrera également dans le classement général de la série.

Classement

Le premier post de la série génère un classement.

Pour vous assurer que vos réponses s'affichent, veuillez commencer chaque réponse par un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores dans le titre, en les barrant. Par exemple:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(La langue n'est pas actuellement affichée, mais l'extrait de code l'exige et l'analyse, et je pourrai ajouter un classement par langue à l'avenir.)

Martin Ender
la source
Attendez, sommes-nous autorisés à utiliser des RNG à plage non entière?
mniip
Les réponses existantes de PS 2 semblent utiliser [0, 1) des RNG à virgule flottante, est-ce autorisé?
mniip
@mniip Oui, les RNG à virgule flottante sont autorisés, à condition qu'ils soient uniformes, semables et capables de renvoyer le nombre requis de flotteurs distincts.
Martin Ender

Réponses:

8

Dyalog APL, 33 octets

{(.5*⍨¯2×⍟?0)×1○○2×?0}¨⍳⎕⊣⎕rl←1+⎕

Box-Muller :

⎕         ⍝ evaluated input
⎕rl←1+⎕   ⍝ set APL's random seed to 1+⎕ (S)
          ⍝   add 1 because ⎕rl←0 has special meaning: sets the seed randomly
{ }¨⍳N    ⍝ do the thing in braces N times
?0        ⍝ random number 0≤x<1
1○○2×A    ⍝ sin(2πA)
.5*⍨¯2×⍟B ⍝ sqrt(-2lnB)
ngn
la source
Je suis sûr que cela ne peut être battu par aucune autre langue.
Zero Fibre
2
Cela ne répond pas à cette règle: "En particulier, s'il est appelé une fois avec (S, N1) et une fois avec (S, N2), les premières entrées min (N1, N2) des deux sorties doivent être identiques."
marinus
@marinus Merci, corrigé. J'ai également changé ⎕rlpour être S+1parce qu'il ⎕rl←0a une signification particulière.
ngn
Vous n'avez probablement pas réellement besoin de la +1, tout ce qu'elle dit, c'est que vous devez prendre en charge au moins 2 ^ 16 valeurs différentes. Donc, travailler correctement dans la plage [1..2 ^ 16] devrait être OK.
marinus
S = 0 rendrait le calcul non répétable, ce qui viole la règle que vous avez citée ci-dessus.
ngn
8

R, 68 octets

function(S,N){set.seed(S);sqrt(-2*log(runif(N)))*cos(2*pi*runif(N))}

Cela utilise la runif()fonction, qui génère des écarts aléatoires à partir d'une distribution uniforme. Le germe pour la génération de nombres aléatoires est spécifié à l'aide de set.seed(), qui utilise par défaut l'algorithme de Mersenne-Twister avec une période de 2 ^ 19937-1.

Le résultat est un vecteur R de longueur N contenant les écarts normaux standard calculés.

Il utilise la méthode de Box-Muller: pour deux variables aléatoires uniformes indépendantes U et V, entrez la description de l'image ici

Alex A.
la source
Si c'est une syntaxe valide dans R, vous pouvez omettre la f=(la fonction n'a pas nécessairement besoin d'être nommée, si les fonctions sans nom sont quelque chose dans votre langage).
Martin Ender
@ MartinBüttner: J'apprécie la suggestion mais à ma connaissance, R ne saurait que faire d'une fonction sans nom.
Alex A.
De plus, je reçois toujours un message d'erreur Error: unexpected '}' in "f=fu..., êtes-vous sûr d'obtenir les mêmes premiers numéros si vous appelez f(0,1)et f(0,2)?
flawr
4

Dyalog APL, 42 34

{⎕RL←⍺⋄{(.5*⍨¯2×⍟⍺)×1○⍵×○2}/?⍵2⍴0}

C'est une fonction qui prend Scomme argument de gauche et Ncomme argument de droite.

     5{⎕RL←⍺⋄{(.5*⍨¯2×⍟⍺)×1○⍵×○2}/?⍵2⍴0}10
3.019132549 ¯0.2903143175 ¯0.7353414637 1.421417015 2.327544764 ¯0.00005019747711 ¯0.9582127248 ¯0.2764568462
      ¯0.1602736853 ¯0.9912352616
     5{⎕RL←⍺⋄{(.5*⍨¯2×⍟⍺)×1○⍵×○2}/?⍵2⍴0}20
3.019132549 ¯0.2903143175 ¯0.7353414637 1.421417015 2.327544764 ¯0.00005019747711 ¯0.9582127248 ¯0.2764568462
      ¯0.1602736853 ¯0.9912352616 0.642585109 ¯0.2450019151 ¯0.415034463 0.03481768503 ¯0.4621212815 ¯0.760925979
      0.2592913013 1.884867889 ¯0.9621252731 0.3062560446

Il s'agit d'une implémentation de la transformation Box-Muller, utilisant l'opérateur aléatoire intégré de Dyalog APL ?, qui par défaut est un twister Mersenne qui renvoie des valeurs 64 bits, ce qui devrait être suffisant.

Explication:

  • ⎕RL←⍺: définissez la graine aléatoire sur .
  • ?⍵2⍴0: générer des paires de nombres aléatoires entre 0 et 1.
  • {... }/: appliquez la fonction suivante à chaque paire:
    • (.5*⍨¯2×⍟⍺)×1○⍵×○2: calcule la Z0valeur ( sqrt(-2 ln ⍺)×cos(2π⍵)).
marinus
la source
1
Dans la version 14.0, ?0renvoie un nombre à virgule flottante compris entre 0 et 1.
ngn
3

Perl, 67

sub f{srand$_[0];map{cos(atan2(1,1)*rand 8)*sqrt-2*log rand}1..pop}

Box-Muller comme dans les autres entrées. fprend les paramètres dans l'ordre S, N.

Utilisation:

$ perl -le 'sub f{srand$_[0];map{cos(atan2(1,1)*rand 8)*sqrt-2*log rand}1..pop}print for f(5,3)'
-1.59212831801942
0.432167710756345
-0.533673305924252
nutki
la source
3

Java, 164 161 octets

class B extends java.util.Random{B(int s,int n){super(s);for(;n-->0;System.out.println(Math.sqrt(-2*Math.log(nextDouble()))*Math.cos(2*Math.PI*nextDouble())));}}

Cela prend l'entrée via la fonction et la sortie via la sortie standard. Il utilise la méthode Box-Muller.

Le numéro un
la source
5
s=0;s++<n;-> ;n-->0;?
Geobits
1
@Geobits ressemble à un lambda: D
TheNumberOne
3

Commodore 64 Basic, 76 70 63 octets

1INPUTS,N:S=R/(-S):F┌I=1TON:?S●(-2*LOG(R/(1)))*S╮(2*π*R/(1)):N─

Étant donné que le jeu de caractères PETSCII contient certains symboles non présents dans Unicode, j'ai effectué des substitutions: /= SHIFT+N, = SHIFT+O, = SHIFT+Q, = SHIFT+I, =SHIFT+E

Cela implémente la transformation Box-Muller standard pour générer les nombres; J'ai choisi la moitié sin (x) de la transformation parce que Commodore 64 Basic a un raccourci à deux caractères pour sin(), mais pas pour cos().

Bien que le manuel indique autrement, la valeur de l'argument à RND ne importe: si un nombre négatif est passé, le générateur de nombres aléatoires est non seulement réensemencées, il est réensemencées avec ce numéro . Cela rend l'ensemencement beaucoup plus simple: au lieu d'avoir besoin de POKEcinq emplacements de mémoire, je dois simplement faire un appel à ne rien faire RND, ce qui réduit le code de deux lignes / 121 octets à 1 ligne / 76 octets.

Edit: Golfed six bytes off en réalisant que je pouvais combiner les deux INPUTdéclarations, et que l'espace après TOétait facultatif.

Edit: Golfed sept autres off: Commodore Basic a, en fait, Pi comme constante intégrée, et il est même saisissable sur un clavier moderne ( SHIFT+PgDn, au cas où vous vous poseriez la question).

marque
la source
3

80386 code machine, 72 octets

Hexdump du code:

60 8b 7c 24 24 33 ed 8d 75 fb 8d 46 79 f7 e2 f7
f6 8b da b3 7f 0f cb d1 eb 89 1f d9 07 d9 e8 de
e9 33 ee 75 e5 d9 ed d9 c9 d9 f1 dc c0 d9 e0 d9
fa d9 c9 d9 eb de c9 dc c0 d9 ff de c9 d9 1f 83
c7 04 e2 c6 61 c2 04 00

Voici le code source (peut être compilé par Visual Studio):

__declspec(naked) void __fastcall doit(int count, unsigned seed, float* output)
{
    _asm {
                                // ecx = count
                                // edx = seed
        // save registers
        pushad;
        mov edi, [esp + 0x24];  // edi = pointer to output
        xor ebp, ebp;           // ebp = 0
        lea esi, [ebp - 5];     // esi = 4294967291 (a prime number)

    myloop:
        // Calculate the next random number
        lea eax, [esi + 121];   // eax = 116
        mul edx;
        div esi;
        mov ebx, edx;

        // Convert it to a float in the range 1...2
        mov bl, 0x7f;
        bswap ebx;
        shr ebx, 1;

        // Convert to range 0...1 and push onto the FPU stack
        mov [edi], ebx;
        fld dword ptr [edi];
        fld1;
        fsubp st(1), st;

        // Make 2 such random numbers
        xor ebp, esi;
        jnz myloop;

        // Calculate sqrt(-2*ln(x))
        fldln2;
        fxch;
        fyl2x;
        fadd st, st(0);
        fchs;
        fsqrt;

        // Calculate cos(2*pi*y)
        fxch st(1);
        fldpi;
        fmul;
        fadd st, st(0);
        fcos;

        // Calculate and write output
        fmulp st(1), st;
        fstp dword ptr [edi];
        add edi, 4;

        // Repeat
        loop myloop

        // Return
        popad;
        ret 4;
    }
}

Ici, j'utilise un générateur de nombres aléatoires Lehmer . Il utilise l'algorithme suivant:

x(k+1) = 116 * x(k) mod 4294967291

Ici, 4294967291 est un grand nombre (2 ^ 32-5) et 116 est un petit nombre (moins de 128; voir ci-dessous) qui est sa racine primitive . J'ai choisi une racine primitive qui a une distribution plus ou moins aléatoire de zéros et de uns en représentation binaire (01110100). Ce RNG a la période maximale possible de 4294967290, si la semence n'est pas nulle.


Les nombres relativement petits que j'ai utilisés ici (116 et 4294967291, qui peuvent également être représentés par -5) me permettent de profiter du leacodage des instructions:

8d 46 79     lea eax, [esi+121]

Il est assemblé à 3 octets si les nombres peuvent tenir dans 1 octet.


La multiplication et la division utilisent edxet eaxcomme registres de travail, c'est pourquoi j'ai fait seedle deuxième paramètre à la fonction (la fastcallconvention d'appel utilise edxpour passer le deuxième paramètre). De plus, le premier paramètre est passé ecx, ce qui est un bon endroit pour tenir un compteur: une boucle peut être organisée en 1 instruction!

e2 c6        loop myloop

Pour convertir un entier en nombre à virgule flottante, j'ai exploité la représentation des nombres à virgule flottante simple précision: si je mets les 9 bits de haut (exposant) sur le motif de bits 001111111et que je laisse les 23 bits de bas au hasard, je vais obtenir un nombre aléatoire compris entre 1 et 2. J'ai pris l'idée d' ici . Pour définir les 9 bits les plus élevés, j'ai utilisé du bidouillage sur ebx:

mov ebx, edx;    xxxxxxxx|yyyyyyyy|zzzzzzzz|aaaaaaaa
mov bl, 0x7f;    xxxxxxxx|yyyyyyyy|zzzzzzzz|01111111
bswap ebx;       01111111|zzzzzzzz|yyyyyyyy|xxxxxxxx
shr ebx, 1;      00111111|1zzzzzzz|zyyyyyyy|yxxxxxxx

Pour générer deux nombres aléatoires, j'ai utilisé une boucle imbriquée de 2 itérations. Je l'ai organisé avec xor:

xor ebp, esi;    first time, the result is -5
jnz myloop;      second time, the result is 0 - exit loop

Le code à virgule flottante implémente la transformation Box-Muller .

anatolyg
la source
2

Haskell, 118  144 

import System.Random;h z=let(u,r)=random z in(cos$2*pi*fst(random r)::Float)*sqrt(-2*log u):h r;g=(.(h.mkStdGen)).take

Exemple d'utilisation:

*Main> g 3 0x6AE4A92CAFA8A742
[0.50378895,-0.20593005,-0.16684927]
*Main> g 6 0x6AE4A92CAFA8A742
[0.50378895,-0.20593005,-0.16684927,1.1229043,-0.10026576,0.4279402]
*Main> g 6 0xE09B1088DF461F7D
[2.5723906,-0.5177805,-1.3535261,0.7400385,3.5619608e-3,-8.246434e-2]

Le type de retour de randomest contraint à Float, ce qui fait randomgénérer un flottant uniforme dans [0, 1). À partir de là, c'est une formule simlpe box-muller avec une magie inutile pour la génération de listes.

mniip
la source
2

Golflua, 63 70

Infos et instructions Golflua.

\g(n,s)`_ENV,b=M,{}rs(s)~@i=1,n b[i]=q(l(r()^-2))*c(r()*pi)$~b$

Renvoie une table contenant les valeurs. Dans l'exemple que j'utilise ~T.u( ), qui est le même que return table.unpack( )dans lua.

> ~T.u(g(3,1234567))
0.89302672974232 0.36330401643578 -0.64762161593981
> ~T.u(g(5,1234567))
0.89302672974232 0.36330401643578 -0.64762161593981 -0.70654636393063 -0.65662878785425
> ~T.u(g(5,7654321))
0.3867923683064 -0.31758512485963 -0.58059120409317 1.2079459300077 1.1500121921242

De nombreux caractères ont été enregistrés en définissant l'environnement de la fonction sur M(aka math).

mniip
la source
2

SAS, 108

J'ai déjà posté une réponse en R plus courte que celle-ci, mais il y a très peu de réponses SAS sur PPCG, alors pourquoi ne pas en ajouter une autre?

%macro f(s,n);data;do i=1 to &n;x=sqrt(-2*log(ranuni(&s)))*cos(8*atan2(1,1)*ranuni(&s));put x;end;run;%mend;

Avec un espace blanc:

%macro f(s, n);
    data;
        do i = 1 to &n;
            x = sqrt(-2 * log(ranuni(&s))) * cos(8 * atan2(1, 1) * ranuni(&s));
            put x;
        end;
    run;
%mend;

Ceci définit une macro qui peut être appelée comme %f(5, 3). La macro exécute une étape de données qui parcourt les entiers 1 à N, et à chaque itération, elle calcule un écart normal aléatoire à l'aide de Box-Muller et l'imprime dans le journal à l'aide de l' putinstruction.

SAS n'a pas intégré pour pi, donc le mieux que nous puissions faire est de l'approximer avec arctangent.

La ranuni()fonction (qui est obsolète mais nécessite quelques caractères de moins que la fonction plus récente) renvoie un nombre aléatoire à partir d'une distribution uniforme. La documentation SAS ne donne pas beaucoup de détails sur l'implémentation RNG, sauf qu'elle a une période de 2 ^ 31-2.

Dans les macros SAS, les variables de macro sont référencées avec un précédent &et résolvent leurs valeurs au moment de l'exécution.

Comme vous l'avez probablement vu, SAS est rarement un concurrent réel dans un concours de .

Alex A.
la source
2

Java, 193 octets

Bien que cela ne bat pas le leader Java actuel, j'ai décidé de publier quand même pour montrer une méthode de calcul différente. C'est une version golfée d'OpenJDK nextGaussian().

class N extends java.util.Random{N(int s,int n){super(s);for(float a,v;n-->0;System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))for(a=0;a>=1|a==0;a=v*v+(v=2*nextFloat()-1)*v)v=2*nextFloat()-1;}}

Avec des sauts de ligne:

class N extends java.util.Random{
    N(int s,int n){
        super(s);
        for(float a,v;
            n-->0;
            System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))
                for(a=0;
                    a>=1|a==0;
                    a=v*v+(v=2*nextFloat()-1)*v)v=2*nextFloat()-1;
    }
}
Géobits
la source
2
+1 pour avoir utilisé Marsaglia (ou plutôt pour ne pas utiliser le Box-Muller simple);)
Martin Ender
Cela ne peut-il pas être un lambda? Quelque chose comme:(s,n)->{java.util.Random r=new java.util.Random(s);for(float a,v;n-->0;System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))for(a=0;a>=1|a==0;a=v*v+(v=2*r.nextFloat()-1)*v)v=2*r.nextFloat()-1;}
Justin
2
@Quincunx je pourrais, pour un octet. Mais je n'aime pas cacher mes déclarations de fonctions dans du code non compté, quel que soit le consensus actuel sur les méta à ce sujet. Ça vaut le seul octet pour moi;)
Geobits
2

T-SQL, 155 octets

CREATE PROC R(@S BIGINT,@N INT)AS
DECLARE @ INT=0,@K INT=8388607WHILE @<@N
BEGIN
SELECT SQRT(-2*LOG(RAND(@S*@%@K)))*COS(2*PI()*RAND(@S*9*@%@K))SET @+=1
END

À utiliser avec EXEC RS, N car il n'y a pas STD_IN dans T-SQL où S et N sont respectivement la graine et N. S produira des séquences "aléatoires" (RAND (graine) est une très mauvaise implémentation de nombres aléatoires) lorsque S> 2 ^ 16 (probablement avant cela, mais je ne le garantis pas). Utilise Box-Muller comme la plupart des solutions jusqu'à présent. 8388607 est 2 ^ 23-1, ce qui devrait, espérons-le, générer 2 ^ 20 valeurs différentes.

bmarks
la source
2

Powershell, 164 octets

Param($s,$n)$q=2147483647
$a=GET-RANDOM -SETSEED $s
FOR(;$n---gt0;){$a=GET-RANDOM
$b=GET-RANDOM
[math]::SQRT(-2*[math]::LOG($a/$q))*[math]::COS(2*[math]::PI*$b/$q)}

Identique à la plupart des réponses avec Box-Muller. Pas très expérimenté avec Powershell, donc toute aide au golf serait appréciée.

bmarks
la source
2

Rubis, 72 octets

->n,s{include Math;srand s;n.times{p sqrt(-2*log(rand))*sin(2*rand*PI)}}

Entrée (en tant que fonction lambda):

f.(6, 12353405)

Production:

-1.1565142460805273
0.9352802655317097
1.3566720571574993
-0.9683973210257978
0.9851210877202192
0.14709635752306677

PS: Je voudrais savoir si cela peut être approfondi. Je suis juste un débutant.

Zéro fibre
la source
@ MartinBüttner Je pense que j'utilise trop de C ces jours-ci. Totalement oublié.
Zero Fibre
2

Matlab, 77

La première entrée doit être n, la seconde s.

a=input('');
rand('seed',a(2));
for i=1:a;
    (-2*log(rand))^.5*cos(2*pi*rand)
end
flawr
la source
2

Octave, 91 96 88 octets

function r=n(s,n)rand("seed",s);x=rand(2,n);r=cos(2*pi*x(1,:)).*sqrt(-2*log(x(2,:)));end

Ou, avec des espaces:

function r=n(s,n)
  rand("seed",s);
  x=rand(2,n);
  r=cos(2*pi*x(1,:)).*sqrt(-2*log(x(2,:)));
end

Réglez la graine à l'avant et utilisez la méthode Box-Mueller.

NB: Octave permet de générer des tableaux de nombres aléatoires et peut utiliser des opérations standard sur ces tableaux qui produisent des sorties de tableau. L' .*opérateur est la multiplication élément par élément de deux tableaux pour produire le résultat.

dcsohl
la source
Je pense que cela ne remplit pas les conditions, si vous appelez n(0,1)et que n(0,2)vous obtenez des premiers numéros différents, n'est-ce pas ?
flawr
Merde, tu as raison. Je l'ai réparé mais cela m'a coûté 5 octets ...
dcsohl
2

Pyth, 32 octets

Aucun Python n'est actuellement utilisé dans les super-guillemets en raison des nouvelles fonctions de Pyth. Encore un autre Box-Mueller.

 .xvzVQ*@_y.lOZ2.71 2.ty*3.14OZ1

Cet espace au début est important.

.xvz             Seed RNG with evaluated input
VQ               For N in second input
*                Multiplication
 @       2       Square root
   _y            Times negative 2
    .l )         Natural log
     OZ          Of random float (RNG with zero give [0, 1) float)
 .t       1      Cosine from list of trig functions
  y              Double
   *             Multiplication
    .nZ          Pi from constants list
    OZ           Random Float

L'ensemencement ne semble pas fonctionner dans l'interpréteur en ligne, mais il fonctionne très bien dans la version locale. L'interprète en ligne semble être corrigé, voici donc un permalien: permalien

Maltysen
la source
1
Cela utilise une fonctionnalité de Pyth ( .nZ) qui n'était pas implémentée lorsque la question a été posée. (Elle a en fait été mise en œuvre aujourd'hui.) Par conséquent, cette réponse ne devrait pas faire partie du concours ( meta.codegolf.stackexchange.com/questions/4867/… ).
Jakube
K, je reviens à la solution de 32 caractères
Maltysen
Ouais, ce serait mieux. Vous pouvez toujours montrer votre nouvelle solution dans une section séparée de votre réponse. Mais le code de vos concurrents devrait être celui qui fonctionne avec l'ancien Pyth.
Jakube
1
Btw, je ne pense pas que la solution 32 devrait être valable non plus. Puisqu'il utilise la graine aléatoire initialisée, qui n'a été ajoutée qu'il y a environ 5 jours.
Jakube
1

STATA, 85 octets

di _r(s)_r(n)
set se $s
set ob $n
g a=sqrt(-2*ln(runiform()))*cos(2*runiform()*_pi)
l

Prend l'entrée via la norme dans (le premier nombre est S, puis N). Définit la valeur de départ à S. Définit le nombre d'observations à N. Fait une variable et définit sa valeur à la valeur de transformation de Box Muller (merci à @Alex de l'avoir montré). Répertorie ensuite toutes les observations dans un tableau avec l'en-tête de colonne a et les numéros d'observation à côté d'eux. Si cela ne vous convient pas, faites-le moi savoir et je pourrai supprimer les en-têtes et / ou les numéros d'observation.

bmarks
la source
1

R, 89 octets

Je sais que R a déjà été fait, mais je voulais montrer une approche différente de la Box-Muller que tout le monde utilisait. Ma solution utilise le théorème de limite centrale .

f=function(S,N){set.seed(S);a=1000;for(i in(1:N)){print(sqrt(12/a)*(sum(runif(a))-a/2))}}
Michal
la source
1
Je crains, le théorème central limite ne satisfait pas "l'algorithme que vous choisissez doit produire une distribution normale théoriquement exacte". Peu importe le nombre de variables uniformes que vous additionnez, tant que la somme est finie, la distribution normale sera toujours approximative. (Bien que le théorème de la limite centrale soit une bonne idée, j'ai dû l'exclure précisément parce que la valeur à utiliser adans votre code n'est pas claire, de sorte que le résultat est "juste".)
Martin Ender
1
Ça valait le coup;)
Michal
1

TI-Basic, 74 octets

Prompt S,N:S→rand:For(X,1,N:0→A:0→V:0→W:While A≥1 or A=0:2rand-1→V:2rand-1→W:V²+W²→A:End:Disp VW√(Aֿ¹-2log(A:End

1      1111111   11   1111111111111111111     1111   111111   1111111   11111111111111  11    111111111   111

C'est en ¹fait l'opérateur inverse.

Ypnypn
la source
1

Perl, 150 108 107 octets

Cela utilise la méthode polaire Marsaglia . Appelé avec f (S, N).

Déplacement de l'affectation de $adans le calcul de $c.

107:

sub f{srand$_[0];map{do{$c=($a=-1+2*rand)**2+(-1+2*rand)**2}until$c<1;print$a*sqrt(-2*log($c)/$c)}1..$_[1]}

Suppression du stockage des numéros de rechange et de la définition de $b.

108:

sub f{srand$_[0];map{do{$a=-1+2*rand,$c=$a**2+(-1+2*rand)**2}until$c<1;print$a*sqrt(-2*log($c)/$c)}1..$_[1]}

150:

sub f{srand$_[0];map{$h?$h=!print$s:do{do{$a=-1+2*rand,$b=-1+2*rand,$c=$a*$a+$b*$b}until$c<1;$d=sqrt(-2*log($c)/$c);$s=$b*$d;$h=print$a*$d;}}1..$_[1]}
Bonsaigin
la source
1

Swift, 144 142

Rien d'intelligent, juste de voir comment Swift fonctionne.

import Foundation;func r(s:UInt32,n:Int){srand(s);for i in 0..<n{println(sqrt(-2*log(Double(rand())/0xffffffff))*sin(2*Double(rand())*M_PI))}}

J'espérais pouvoir utiliser (0 ... n) .map {} mais le compilateur ne semble pas reconnaître la carte {} à moins que vous n'utilisiez un paramètre.

GoatInTheMachine
la source
bien sûr...? c'estforEach si vous ne voulez pas de valeur de retour, et je suis à peu près sûr que _ inc'est obligatoire
ASCII uniquement
à quoi /0xffffffffsert btw
ASCII uniquement
1

Haskell , 97 octets

import System.Random
h(a:b:c)=sqrt(-2*log a::Float)*cos(2*pi*b):h c
f a=take a.h.randoms.mkStdGen

Essayez-le en ligne!

Juste votre transformation Box-Muller de base, sur une liste infinie de nombres aléatoires.

Angs
la source
0

SmileBASIC, 81 octets

Eh bien, maintenant que j'ai répondu à la première question, je dois faire tout le reste ...

Générer des nombres aléatoires est pas cher, mais l' ensemencement de la RNG utilise la plus longue fonction builtin dans la langue, RANDOMIZE.

DEF N S,N
RANDOMIZE.,S
FOR I=1TO N?SQR(-2*LOG(RNDF()))*COS(PI()*2*RNDF())NEXT
END

Peut-être existe-t-il un moyen d'optimiser la formule. Je ne vois pas comment il est nécessaire d'utiliser deux appels RNG.

12Me21
la source
Il est nécessaire d'avoir deux échantillons indépendants pour la transformation Box-Muller
ASCII uniquement