Bonne journée Pi tout le monde! Pour aucune raison, j'essaie de construire un estimateur de Monte Carlo de Pi aussi court que possible. Pouvons-nous en construire un qui peut tenir dans un tweet?
Pour clarifier, ce que j'ai à l'esprit est l'approche typique consistant à dessiner des points aléatoires à partir du carré unitaire et à calculer le rapport qui se situe dans le cercle unitaire. Le nombre d'échantillons peut être codé en dur ou non. Si vous les codez en dur, vous devez utiliser au moins 1000 échantillons. Le résultat peut être renvoyé ou imprimé sous forme de virgule flottante, de virgule fixe ou de nombre rationnel.
Aucune fonction trig ou constantes Pi, doit être une approche Monte Carlo.
Il s'agit du code golf, donc la soumission la plus courte (en octets) l'emporte.
la source
((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
map
vous donne- t-il pas un tableau detrue
etfalse
?.filter{...}.size
devrait fonctionner, cependant.Réponses:
80386 code machine,
4038 octetsHexdump du code:
Comment obtenir ce code (à partir du langage d'assemblage):
Il s'agit d'une fonction utilisant la
fastcall
convention d'appel MS (le nombre d'itérations est passé dans le registreecx
). Il renvoie le résultat dans lest
registre.Choses amusantes sur ce code:
rdrand
- seulement 3 octets pour générer un nombre aléatoire!D
) avec le rayon au carré (2^32
) est effectuée automatiquement - le drapeau de report contient le résultat.la source
eax
; lamul
commande la multiplie par elle-même et y met la partie hauteedx
; la partie basse eneax
est jetée.Matlab / Octave, 27 octets
Je sais qu'il existe déjà une réponse Matlab / Octave, mais j'ai essayé ma propre approche. J'ai utilisé le fait que l'intégrale
4/(1+x^2)
entre 0 et 1 est pi.la source
R, 40 (ou 28 ou 24 en utilisant d'autres méthodes)
Python 2, 56
Un autre Python, si numpy est autorisé, mais assez similaire à Matlab / Octave:
la source
Mathematica,
424039 octets (ou 31/29?)J'ai trois solutions à 42 octets:
Ce sont toutes des fonctions sans nom qui prennent le nombre d'échantillons
n
et renvoient une approximation rationnelle π. D'abord, ils génèrent tous desn
points dans le carré unitaire du quadrant positif. Ensuite, ils déterminent le nombre d'échantillons qui se trouvent dans le cercle unitaire, puis ils divisent par le nombre d'échantillons et multiplient par4
. La seule différence réside dans la façon dont ils déterminent le nombre d'échantillons à l'intérieur du cercle unitaire:Count
à la condition queNorm[p] < 1
.1
puis arrondit. Cela transforme les nombres à l'intérieur du cercle d'unité en1
et ceux à l'extérieur vers0
. Après je les résume tousTr
.1.5
, donc je peux utiliser à laRound
place deCeiling
.Aaaaaand en écrivant ceci, il m'est venu à l' esprit qu'il existe en effet une solution plus courte, si je soustrais
2
et utilise ensuiteFloor
:ou enregistrer un autre octet en utilisant les opérateurs de plancher ou de plafond Unicode:
Notez que les trois solutions basées sur l'arrondi peuvent également être écrites avec
Mean
au lieu deTr
et sans/#
, à nouveau pour les mêmes octets.Si d'autres approches basées sur Monte Carlo sont correctes (en particulier, celle que Peter a choisie), je peux faire 31 octets en estimant l'intégrale de ou 29 en utilisant l'intégrale de , cette fois donnée comme un nombre à virgule flottante:
√(1-x2)
1/(1+x2)
la source
CJam,
27 2322 ou 20 octets2 octets enregistrés grâce à Runner112, 1 octet enregistré grâce à Sp3000
Il prend le nombre d'itérations de STDIN en entrée.
C'est aussi simple que possible. Ce sont les étapes principales impliquées:
Expansion du code :
Essayez-le en ligne ici
Si la valeur moyenne de
1/(1+x^2)
est également considérée comme Monte Carlo, cela peut être fait en 20 octets:Essayez-le ici
la source
1dmr
au lieu deKmrK/
, et vérifier si la somme des carrés est supérieure à 1 aveci
au lieu de1>
(je pensais que celui-ci était particulièrement intelligent) .i
astuce est vraiment soignée! Et sacrément le manque de documentation pour1dmr
Python 2,
7775 octetsUtilise 4000 échantillons pour enregistrer des octets
1e3
.la source
...*8000;print a/2e3
.Commodore 64 Basic, 45 octets
Substitutions PETSCII:
─
=SHIFT+E
,/
=SHIFT+N
,┌
=SHIFT+O
Génère 1000 points dans le premier quadrant; pour chacun, ajoute la justesse de "x ^ 2 + y ^ 2 <1" à un décompte en cours, puis divise le décompte par 250 pour obtenir
pi
. (La présence d'un signe moins est due au fait que sur le C64, "true" = -1.)la source
(1)
-il?/
n'est pas le symbole de division, c'est le caractère produit en tapantSHIFT+N
sur un clavier Commodore 64.R/(1)
est la forme de raccourci pourRND(1)
, ie. msgstr "produire un nombre aléatoire entre 0 et 1 en utilisant la graine RNG actuelle".J, 17 octets
Calcule la valeur moyenne des valeurs d'
40000
échantillon de la fonction4*sqrt(1-sqr(x))
dans la plage[0,1]
.Maniablement
0 o.x
retourssqrt(1-sqr(x))
.la source
> <> (Poisson) , 114 octets
Maintenant,> <> n'a pas de générateur de nombres aléatoires intégré. Il a cependant une fonction qui envoie le pointeur dans une direction aléatoire. Le générateur de nombres aléatoires dans mon code:
Il génère essentiellement des bits aléatoires qui composent un nombre binaire, puis convertit ce nombre binaire aléatoire en décimal.
Le reste n'est que les points réguliers de l'approche carrée.
Utilisation: lorsque vous exécutez le code, vous devez vous assurer de préremplir la pile (-v dans l'interpréteur python) avec le nombre d'échantillons, par exemple
résultats
la source
Matlab ou Octave 29 octets (merci à flawr!)
(Je ne sais pas trop si <1 est OK. J'ai lu que cela devrait être <= 1. Mais quelle est la probabilité de dessiner exactement 1 ...)
Matlab ou Octave 31 octets
la source
mean(sum(rand(2,4e6).^2)<1)*4
.Java, 108 octets
Quatre mille itérations, ajoutant 0,001 à chaque fois que le point se trouve à l'intérieur du cercle unitaire. Des trucs assez basiques.
Remarque: Oui, je sais que je peux perdre quatre octets en passant
π
à un caractère à un octet. J'aime ça comme ça.la source
Javascript: 62 octets
J'ai utilisé la réponse javascript précédente (maintenant supprimée) et rasé 5 octets.
la source
GolfScript (34 caractères)
Démo en ligne
Cela utilise un point fixe car GS n'a pas vraiment de virgule flottante. Il abuse légèrement de l'utilisation du point fixe, donc si vous voulez changer le nombre d'itérations, assurez-vous que c'est deux fois une puissance de dix.
Crédit xnor pour la méthode particulière Monte Carlo employé.
la source
Python 2,
908581 octetsrenvoie
3.14120037157
par exemple. Le nombre d'échantillons est 4782969 (9 ^ 7). Vous pouvez obtenir un meilleur pi avec 9 ^ 9 mais vous devrez être patient.la source
range(9**7)
par[0]*9**7
ou quelque chose, puisque vous n'utilisez pasi
. Et la liste n'est pas trop longue pour rencontrer des problèmes de mémoire.range()
mais j'avais complètement oublié cette astuce.[0]9**7
que la syntaxe n'est pas valide.Rubis, 39 octets
L'un des points forts est que celui-ci est capable d'utiliser la
8e5
notation, ce qui le rend extensible jusqu'à ~ 8e9 échantillons dans le même nombre d'octets de programme.la source
Perl 6 , 33 octets
Essayez-le en ligne!
Il s'agit d'une fonction qui prend le nombre d'échantillons comme argument.
la source
Scala,
877766 octetsla source
1000
par8000
et250d
avec2e4
vous enregistrez un octet et augmentez le nombre d'échantillons d'un facteur 8.Pure Bash, 65 octets
Prend un seul paramètre de ligne de commande qui est multiplié par 4 pour donner le nombre d'échantillons. L'arithmétique de Bash est uniquement un entier, donc un rationnel est produit. Cela peut être canalisé
bc -l
pour la division finale:la source
Joe ,
2019 octetsRemarque: cette réponse n'est pas concurrente, car la version 0.1.2, qui ajoutait de l'aléatoire, a été publiée après ce défi.
Fonction nommée F:
Fonction sans nom:
Ces deux éléments prennent le nombre d'échantillons comme argument et renvoient le résultat. Comment travaillent-ils?
L'exemple s'exécute:
la source
dc, 59 caractères (les espaces sont ignorés)
J'ai testé cela sur Plan 9 et OpenBSD, donc j'imagine que cela fonctionnera sur Linux (GNU?)
dc
.Explication par ligne:
i
si 1 est supérieur à la somme de leurs carrés] dans le registreu
.x
de 1] dans le registrei
.u
, incrémenter le registrem
, puis exécuter le registrez
si le registrem
est supérieur au registren
] dans le registrez
.Réglez l'échelle à 5 décimales.
z
.x
(le nombre de visites) par registren
(le nombre de points), multipliez le résultat par 4 et imprimez.Cependant, j'ai triché:
Le programme a besoin d'une réserve de flotteurs aléatoires entre 0 et 1.
Usage:
Essai:
Maintenant avec moins de triche (100 octets)
Quelqu'un a souligné que je pouvais inclure un simple prng.
http://en.wikipedia.org/wiki/RANDU
Non golfé
Essai:
la source
Pyth, 19
Donnez le nombre d'itérations souhaité en entrée.
Manifestation
Comme Pyth n'a pas de fonction "Nombre flottant aléatoire", j'ai dû improviser. Le programme choisit deux entiers positifs aléatoires inférieurs à l'entrée, les carrés, les sommes et comparés à l'entrée au carré. Cela a été effectué un nombre de fois égal à l'entrée, puis le résultat est multiplié par 4 et divisé par l'entrée.
Dans les nouvelles connexes, j'ajouterai prochainement une opération de nombre à virgule flottante aléatoire à Pyth. Ce programme n'utilise cependant pas cette fonctionnalité.
Si nous interprétons "Le résultat peut être renvoyé ou imprimé sous forme de virgule flottante, de virgule fixe ou de nombre rationnel". libéralement, alors l'impression du numérateur et du dénominateur de la fraction résultante devrait être suffisante. Dans ce cas:
Pyth, 18
Il s'agit d'un programme identique, avec l'opération de division en virgule flottante (
c
) supprimée.la source
Julia, 37 octets
Le nombre d'échantillons est de 65536 (= 4 ^ 8).
Une variante légèrement plus longue: une fonction avec le nombre d'échantillons
s
comme seul argument:la source
C, 130 octets
Non golfé:
la source
f()
. Quel compilateur avez-vous utilisé? Voir tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/…En fait , 14 octets (non concurrents)
Essayez-le en ligne!
Cette solution n'est pas concurrente car la langue est postérieure au challenge. Le nombre d'échantillons est donné en entrée (plutôt que codé en dur).
Explication:
la source
Raquette 63 octets
Utilisation de la méthode de réponse en langage R par @Matt:
Non golfé:
Essai:
Sortie (fraction):
Comme décimal:
la source
Fortran (GFortran) ,
8483 octetsEssayez-le en ligne!
This code is very bad wrote. It will fail if gfortran decide to initialize variable
A
with other value then 0 (which occurs 50% of the compilations, approximately) and, ifA
is initialized as 0, it will always generate the same random sequence for the given seed. Then, the same value for Pi is printed always.This is a much better program:
Fortran (GFortran),
10099 bytesTry it online!
(One byte saved in each version; thanks Penguino).
la source
Japt, 26 or 18 bytes
Try it online!
Analogous to Optimizer's answer, mainly just trying to learn Japt.
Takes the number of iterations to run for as the implicit input
U
.If
1/(1+x^2)
is allowed (instead of two separate randoms), then we can achieve 18 bytes with the same logic.la source
Mh
calculate the hypotenuse rather than doing it yourself ;-) Also, you can usex
to take the sum of an array, rather than reducing by addition:o x@MhMr Mr)<1Ã*4/U
Mh
like that, thanks! Your two-random answer is nearly as short as my answer with only one random, that's pretty cool. I'll keepx
in mind, I tend to use reduction a lot when trying to golf stuff, so this will come in very handy.F#, 149 bytes
Try it online!
As far as I can make out, to do this kind of running total in F# it's shorter to create an array of numbers and use the
Seq.sumBy
method than use afor..to..do
block.What this code does it that it creates a collection of floating-point numbers from 1 to
s
, performs the functionfun x->...
for the number of elements in the collection, and sums the result. There ares
elements in the collection, so the random test is dones
times. The actual numbers in the collection are ignored (fun x->
, butx
is not used).It also means that the application has to first create and fill the array, and then iterate over it. So it's probably twice as slow as a
for..to..do
loop. And with the array creation memory usage is in the region of O(f**k)!For the actual test itself, instead of using an
if then else
statement what it does is it calculates the distance (q()+q()|>Math.Sqrt
) and rounds it down withMath.Floor
. If the distance is within the circle, it'll be rounded down to 0. If the distance is outside the circle it'll be rounded down to 1. TheSeq.sumBy
method will then total these results.Note then that what
Seq.sumBy
has totalled is not the points inside the circle, but the points outside it. So for the result it takess
(our sample size) and subtracts the total from it.It also appears that taking a sample size as a parameter is shorter than hard-coding the value. So I am cheating a little bit...
la source
Haskell,
11611411096 bytesBecause dealing with
import System.Random; r=randoms(mkStdGen 2)
would take too many precious bytes, I generate an infinite list of random numbers with the linear congruential generator that some say is almost cryptographically strong:x↦x*9+1 mod 8^9
, which by the Hull-Dobell Theorem has the full period of8^9
.g
yields4
if the random number point is inside the circle for pairs of random numbers in[0..8^9-1]
because this eliminates a multiplication in the formula used.Usage:
Try it online!
la source
Perl 5, 34 bytes
The number of samples is taken from stdin. Requires
-p
.Works because:
Try it online!
la source