Objectif
Générez ( N
) des segments de ligne aléatoires de longueur uniforme ( l
), vérifiez s'ils croisent les t
lignes parallèles équidistantes ( ).
Simulation
Que simulons-nous? L'aiguille de Buffon . Lissez le sable dans votre bac à sable, tracez un ensemble de lignes parallèles également espacées (appelez la distance entre les deux t
). Prenez un bâton droit de longueur l
et déposez-le N
fois dans le bac à sable. Soit le nombre de fois qu'il a franchi une ligne c
. Alors Pi = (2 * l * n) / (t * c)
!
Comment simulons-nous cela?
- Prendre connaissance
N,t,l
- Avec
N, t, l
tous des entiers positifs - Procédez comme suit
N
:- Générer une coordonnée entière uniformément aléatoire
x,y
- Avec
1 <= x, y <= 10^6
x,y
est le centre d'un segment de ligne de longueurl
- Générer un entier uniformément aléatoire
a
- Avec
1 <= a <= 180
- Soit
P
le point où le segment de ligne traverserait l'axe des x - Alors
a
c'est l'angle(x,y), P, (inf,0)
- Générer une coordonnée entière uniformément aléatoire
- Compter le nombre
c
de segments de ligne qui traversent la lignex = i*t
pour tout entieri
- Revenir
(2 * l * N) / (t * c)
spécification
- Contribution
- Flexible, saisissez les données de n'importe quelle manière standard (par exemple, paramètre de fonction, STDIN) et dans n'importe quel format standard (par exemple chaîne, binaire)
- Production
- Flexible, donne une sortie de n'importe quelle manière standard (par exemple retour, impression)
- Les espaces blancs, les espaces blancs arrière et avant sont acceptables
- Précision, veuillez fournir au moins 4 décimales de précision (c.-à-d.
3.1416
)
- Notation
- Le code le plus court gagne!
Cas de test
Votre sortie peut ne pas correspondre à ceux-ci, en raison du hasard. Mais en moyenne, vous devriez obtenir cette précision pour la valeur donnée de N, t, l
.
Input (N,t,l) -> Output
----------- ------
10,10,5 -> ?.????
10,100,50 -> ?.????
1000,1000,600 -> 3.????
10000,1000,700 -> 3.1???
100000,1000,700 -> 3.14??
TL; DR
Ces défis sont des simulations d'algorithmes qui ne nécessitent que la nature et votre cerveau (et peut-être quelques ressources réutilisables) pour approximer Pi. Si vous avez vraiment besoin de Pi pendant l'apocalypse zombie, ces méthodes ne gaspillent pas de munitions ! Il y a neuf défis au total.
a
peut-elle également être créée par une autre méthode, si elle est uniforme? (en pensant à une bulle de Gauss 2D)t > l
? Deux solutions ci-dessous font cette hypothèse, ce qui simplifie un peu la vérification de l'intersection.Réponses:
R,
1131007570686765596357 octetsEn tant que langage de programmation statistique et fonctionnel, il n'est pas surprenant que R soit assez bien adapté à ce type de tâche. Le fait que la plupart des fonctions peuvent prendre une entrée vectorisée est vraiment utile pour ce problème, car plutôt que de boucler sur les
N
itérations, nous passons simplement des vecteurs de tailleN
. Merci à @Billywob pour quelques suggestions qui ont conduit à couper 4 octets. Un grand merci à @Primo pour m'avoir patiemment expliqué comment mon code ne fonctionnait pas pour les cas oùt > l
, qui est maintenant corrigé.Essayez-le en ligne!
Exemple de sortie:
Explication
Le problème se résume à déterminer si les deux
x
valeurs de l'aiguille sont de chaque côté d'une ligne parallèle. Cela a des conséquences importantes:y
-les valeurs ne sont pas pertinentesx
axe n'est pas pertinent, seule la position par rapport aux lignes parallèles les plus proches.Il s'agit essentiellement d'une tâche dans un espace à une dimension, où nous générons une ligne de longueur en [0,
l
] (l'anglea
détermine cette longueur), puis nous vérifions combien de fois cette longueur dépasset
. L'algorithme approximatif est alors:x1
valeurs de [0, 1000000]. Puisque des lignes parallèles se produisent à chaquet
point sur l'x
axe -x, la position relativex
estx
modulot
.a
.x2
position en fonction dea
.x1+x2
s'inscritt
, c'est-à-dire prenez la parole(x1+x2)/t
.L'échantillonnage des
N
nombres dans [0, 1e6] modulot
est équivalent à un simple échantillonnage desN
nombres dans [0,t
]. Puisque(x1+x2)/t
est équivalent àx1/t + x2/t
, la première étape devient un échantillonnage à partir de [0,t
] /t
, c'est-à-dire [0, 1]. Heureusement pour nous, c'est la plage par défaut pour larunif
fonction de R , qui renvoieN
des nombres réels de 0 à 1 à partir d'une distribution uniforme.Nous répétons cette étape pour générer
a
, l'angle de l'aiguille.Ces nombres sont interprétés comme un demi-tour (c'est-à-dire
.5
90 degrés). (L'OP demande des degrés de 1 à 180, mais dans les commentaires, il est précisé que toute méthode est autorisée si elle est aussi précise ou plus précise.) Pour un angleθ
,sin(θ)
nous donne la distance sur l'axe des x entre les extrémités de l'aiguille. (Normalement, vous utiliseriez le cosinus pour quelque chose comme ça; mais dans notre cas, nous considérons l'angleθ
comme étant relatif à l'axe des y, pas à l'axe des x (c'est-à-dire qu'une valeur de 0 degré augmente , non à droite ), et donc nous utilisons le sinus, qui fondamentalement décale les nombres.) Multiplié parl
cela nous donne l'x
emplacement de l'extrémité de l'aiguille.Maintenant, nous divisons
t
et ajoutons lax1
valeur. Cela donne(x1+x2)/t
, qui est à quelle distance l'aiguille dépassex1
, en termes de nombre de lignes parallèles. Pour obtenir l'entier du nombre de lignes franchies, nous prenons lefloor
.Nous calculons la somme, en nous donnant le nombre
c
de lignes traversées par des aiguilles.Le reste du code implémente simplement la formule d'approximation de pi, c'est-à-dire
(2*l*N)/(t*c)
. Nous économisons quelques octets entre parenthèses en profitant du fait que(2*l*N)/(t*c) == 2*l*N/t/c
:Et le tout est enveloppé dans une fonction anonyme:
la source
(2*l*N) => 2*l*N
?(2*l*N)/(t*c) = 2*l*N/t/c
vous pouvez donc économiser encore deux octets en sautant également les parenthèses sur la dernière partie.Perl, 97 octets
En comptant le shebang comme un, l'entrée est tirée de stdin, l'espace séparé. Si des valeurs aléatoires non entières étaient autorisées, cela pourrait être un peu plus court.
J'ai pris une liberté, d'approximativement π / 180 comme 71/4068 , qui est précise dans 1,48 · 10 -9 .
Exemple d'utilisation
Substitutions plus ou moins mathématiquement équivalentes
En supposant que la coordonnée x représente le point le plus à gauche de l'aiguille, plutôt que son milieu, comme spécifié dans la description du problème:
89 octets
Le problème spécifie que
x
doit être échantillonné comme un entier aléatoire. Si nous projetons l'espacement des lignes sur un intervalle d'un, cela nous laissera des valeurs de la formen/t
avec0 <= n < t
, pas nécessairement uniformes, si ellest
ne se divisent pas également1e6
. En supposant qu'une distribution uniforme soit néanmoins acceptable:76 octets
Notez que puisque
rand
sera toujours inférieur à un (et donc tronqué à zéro), il n'est pas nécessaire au début de la plage:70 octets
En supposant que l'angle de l'aiguille ne doit pas nécessairement être un degré entier, mais seulement uniformément aléatoire:
59 octets
En supposant que l'angle peut être n'importe quelle distribution uniforme:
52 octets
Ce qui précède est une simulation mathématiquement correcte de l'aiguille de Buffon. Cependant, à ce stade, je pense que la plupart des gens conviendraient que ce n'est pas vraiment ce que la question demandait.
Vraiment le pousser
Nous pourrions simplement jeter la moitié des cas de test, chaque fois que le deuxième point de terminaison est à gauche du premier (plutôt que de les échanger):
47 octets
Notez que les valeurs de
t
etl
sont sans conséquence pour les résultats de l'expérience. Nous pourrions simplement les ignorer (en supposant implicitement qu'elles sont égales):28 octets
Evidemment non compétitif, mais il faut bien l'admettre, il a une certaine élégance.
la source
Python 2, 141 octets
port sans vergogne de rtumbull, sautant déjà
y
car totalement inutile.Le problème est seulement que pi est déjà connu dans le programme.
Le voici (jouable au golf) avec un pi inconnu et aucune fonction trigonométrique
x,y
eng
est seulement pour la direction.la source
from random import randint;from math import cos,pi
. Échouet < l
, par exemple1000000,1000,70000
.