Calculer les chiffres de Pi


15

C'est une tâche quelque peu différente. Calculez 1024 chiffres hexadécimaux de π, en commençant à la 1024e place hexadécimale.

Formellement: votre programme devrait se terminer en moins d'une minute et produire la sortie suivante:

25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5ebd09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd23876053317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbca58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e89a0d6411bd3ae1e7e4900250e2d2071b35e226800bb57b8e0af2464369bf009b91e5563911d59dfa6aa78c14389d95a537f207d5ba202e5b9c5832603766295cfa911c81968414a34a

Le programme avec la durée la plus courte gagne. Vous devez calculer tous les chiffres lors de l'exécution. Vous n'avez pas à implémenter l'algorithme qui calcule π; si votre langue fournit déjà cette fonctionnalité, vous pouvez l'utiliser.


Hah, ça devrait être facile. (+1, toujours) Je parie que je peux le faire exécuter en moins de quelques secondes.
Mateen Ulhaq

@muntoo: Et? Où est ta solution?
FUZxxl

J'ai oublié de le faire. :) BTW, vitesse! = Code-golf.
Mateen Ulhaq

@muntoo: Je sais. Mais je pense aussi que 5 jours est un bon moment pour une tâche aussi facile.
FUZxxl

Réponses:


13

Sauge, 29 car.

Ce n'est pas techniquement de la triche, car les chiffres sont calculés lors de l'exécution. Cela dit, c'est toujours aussi bon marché que l'enfer.

hex(floor(pi*2^8192))[1025:]

1
Certainement pas tricher.
FUZxxl

11
Mmmm, plancher pi.
boîte à pain

13

Utilitaires Shell: 48

curl -sL ow.ly/5u3hc|grep -Eom 1 '[a-f0-9]{1024}'

  • Toutes les sorties sont "calculées" au moment de l'exécution. (grâce à OP affichant la solution)
  • Fonctionne en moins d'une minute. (peut dépendre de la vitesse de votre connexion Internet)

Habituellement, je sous-estime ce type de solutions, car elles constituent un abus courant des règles et ne sont plus drôles. Mais juste parce que vous êtes si sournois de prendre la solution de référence fournie et d'écrire Toutes les sorties sont "calculées" au moment de l'exécution. (grâce à OP qui a publié la solution) , je vous donne un vote positif;)
FUZxxl

Version golf: curl -sL ow.ly/shKGY|grep -Po \\w{99,}(37). Fonctionne dans Dash. Bash aurait besoin d'un octet supplémentaire.
Dennis

6

J, 156, 140, 137 127

d=:3 :'1|+/4 _2 _1 _1*+/(y&(16^-)%1 4 5 6+8*])"0 i.y+9'
,1([:}.'0123456789abcdef'{~[:|.[:<.[:(],~16*1|{.)^:8 d)"0\1024x+8*i.128

Utilisation de la formule BBP.

Ne court pas en moins d'une minute (mais nous avons une réponse J: p)

Exemple pour les 104 premiers chiffres de π (cela fonctionne rapidement):

,1([:}.'0123456789abcdef'{~[:|.[:<.[:(],~16*1|{.)^:8 d)"0\8*i.13x

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89
452821e638d01377be5466cf34e90c6cc0ac29b7

Pourquoi n'utilisez-vous pas #: pour convertir les nombres en hexadécimal?
FUZxxl

Je ne sais pas ce que tu veux dire. #:ne produira pas de chiffres hexadécimaux.
Eelvex

À mon humble avis, il est plus facile d'utiliser #: et une refonte pour générer des chiffres hexadécimaux que votre approche actuelle.
FUZxxl

Tu veux dire quelque chose comme (... 16 #:) Pi? Je pense que nous n'avons pas assez de chiffres, nous devons donc les générer de toute façon.
Eelvex

1
BTW, j'ai découvert qu'il y a le verbe hfdpour convertir des nombres en hexadécimal.
FUZxxl

5

JavaScript, 536

(Sauts de ligne et indentation pour la lisibilité uniquement)

var d='0123456789abcdef',p='',o='',l=3e3,c=0,e='length';d=d+d;
function $(n,r){return n[e]<=r?0:d.indexOf(n[r])}
function g(a,b){for(i=0,t='',s=16;i<l;i++,t+=d[~~(s/b)],s=(s%b)*16);
for(;a--;t=_(t,t,1));return t}
function _(a,b,s){for(i=(a[e]>b[e]?a[e]:b[e])-1,r='',c=0;i>=0;r=(s?
  function(k){c=k>15;return d[k]}($(a,i)+$(b,i)+c):
  function(k){c=k<0;return d[k+16]}($(a,i)-$(b,i)-c))+r,i--);return r}
for(i=0;i<l;i++,p+='2');
for(j=1;j<l;p=_(p,(o+='0')+_(_(_(g(2,8*j+1),g(1,8*j+4)),g(0,8*j+5)),g(0,8*j+6)),1),j++);
console.log(p.slice(1024,2048))

Cela prend environ 25 secondes, sur Google Chrome 14 sur mon ordinateur portable utilisant le noyau Intel i5. Quelqu'un d'autre peut-il jouer au golf avec ce code? Je ne peux pas bien jouer au golf .. :(

Ci-dessous est non-golfé. Je viens de supprimer tous les commentaires et de changer de boucle pour jouer au golf.

Ne parlez pas for(;s>=b;s-=b);s*=16;. Je l'ai changé en s=(s%b)*16. : P

/**
Calculate PI-3 to 3000 (3e3) digits.
a : a
b : b
c : carry
d : digits
e : length
f : get from d
g : calculate (2^a)/b.
i,j, : for looping
l : length to calculate
p : pi
r,t : return value
*/
var d='0123456789abcdef',p='',o='',l=3e3,c=0,e='length';
d=d+d;//for carring

function $(n,r){return n[e]<=r?0:d.indexOf(n[r])}
/*
Calculate (2^a)/b. Assume that 2^a < b.
*/
function g(a,b){
    for(i=0,t='',s=16;i<l;i++){t+=d[~~(s/b)];for(;s>=b;s-=b);s*=16;}
    for(;a--;t=_(t,t,1));return t}
/*
Calculate a±b. (+ when s=1, - when s=0) When calculating minus, assume that 1>b>a>0.
*/
function _(a,b,s){
    for(i=(a[e]>b[e]?a[e]:b[e])-1,r='',c=0;i>=0;
        r=(s?function(k){c=k>15;return d[k]}($(a,i)+$(b,i)+c):
            function(k){c=k<0;return d[k+16]}($(a,i)-$(b,i)-c))+r,i--);return r;
}
/*
Using BBP formula. Calc when j=0...
4/1 - 2/4 - 1/5 - 1/6 = 3.22222222.... (b16)
*/
for(i=0;i<l;i++,p+='2');
//Calc when j>0
for(j=1;j<l;p=_(p,(o+='0')+_(_(_(g(2,8*j+1),g(1,8*j+4)),g(0,8*j+5)),g(0,8*j+6)),1),j++);
console.log(p.slice(1024,2048));

EDIT: Suppression de la fonction totalement inutilisée. (Pourquoi ai-je gardé ça?: /)

PS. 100 premiers chiffres de PI

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be5466cf34e90c6cc0ab


@FUZxxl: Le code non golfé n'était-il pas suffisant? .. :(
JiminP

C'était en effet. Mais à mon humble avis, il semble mieux, si vous utilisez la mise en forme du code au lieu d'utiliser la syntaxe de backtick. Comme je l'ai écrit, n'hésitez pas à revenir si vous n'aimez pas.
FUZxxl

d='0123456789abcdef',l=3e3,p=Array(l+1).join(2),o='',c=0,e='length';d+=d;function _(a,b,s){for(i=(a[e]>b[e]?a[e]:b[e])-1,r='',c=0;i+1;r=d[Z=F(b,i,1)+c,k=F(a,i,1)+(s?Z:16-Z),c=s?k>15:k<16,k]+r,i--);return r}function F(a,b,f){if(f)f=a[e]>b?d.indexOf(a[b]):0;else{for(i=0,f='',s=16;i++<l;f+=d[~~(s/b)],s=(s%b)*16);while(a--)f=_(f,f,1)}return f}for(j=0;++j<l;p=_(p,(o+='0')+_(_(_(F(2,z=8*j+1),F(1,z+3)),F(0,z+4)),F(0,z+5)),1));console.log(p.slice(1024,2048))
Peter Taylor

C'est vraiment toutes les micro-optimisations, bien que certaines semblent assez grandes. La plus grande économie provient de l'élimination des deux fonctions anonymes _au profit de l' ,opérateur. La plus délicate est la fusion de $et gen une seule fonction, avec un argument facultatif pour choisir entre elles. functionet returnsont tous les deux assez chers, donc un if(f)...elseet deux ,1sont un compromis raisonnable.
Peter Taylor

4

PHP 116 114 octets

<?for(;$g?$d=0|($$g=$g--/2*$d+($$g?:2)%$g*$f)/$g--:4613^printf($i++>257?'%04x':'',$e+$d/$f=4*$g=16384)^$e=$d%$f;);

Cette solution calcule tous les pi jusqu'à 2048 chiffres hexadécimaux, quatre chiffres hexadécimaux à la fois, et génère la dernière moitié d'entre eux. Le temps d'exécution est inférieur à 5 secondes. La formule utilisée pour le calcul est la suivante:

pi = 2 + 1/3*(2 + 2/5*(2 + 3/7*(2 + 4/9*(2 + 5/11*(2 + 6/13*(2 + 7/15*(2 + ... )))))))

La précision est obtenue en stockant les restes dans un tableau et en continuant progressivement chacune des 2 ^ 14 divisions.

Python 64 octets

x=p=16385
while~-p:x=p/2*x/p+2*2**8192;p-=2
print('%x'%x)[1025:]

Même méthode que ci-dessus. Fonctionne en environ 0,2 s.

Ou en une ligne en 73 octets :

print('%x'%reduce(lambda x,p:p/2*x/p+2*2**8192,range(16387,1,-2)))[1025:]

3

PARI / GP-2.4, 141

forstep(d=1024,2047,8,y=frac(apply(x->sum(k=0,d+30,16^(d-k)/(8*k+x)),[1,4,5,6])*[4,-2,-1,-1]~);for(i=0,7,y=16*frac(y);printf("%X",floor(y))))

En utilisant la formule Bailey – Borwein – Plouffe (bien sûr).

Fonctionne bien en moins d'une minute.


3

Code C:

long ki,k,e,d=1024;
int  dig,tD=0,c,Co=0,j,js[4]  ={1,4,5,6};
double res=0.0,tres=0.0,gT,ans[4] ={0.0};
while(tD < 1024)
{while(Co<4){ j= js[Co],gT=0.0,ki= 0;
 for(; ki < d+1;ki++){ k = 8*ki+j,e= d-ki,c=1; while(e--) c = 16*c % k; gT+=((double)(c)/(double)k);}
 ans[Co] = (gT - (int)gT),++Co;}
 double gA = 4*ans[0]-2*ans[1]-ans[2]-ans[3];
 gA = (gA<0) ? gA + -1*(int)gA +1 : gA -(int)gA;
 dig=0;while(dig++ < 6 && tD++ < 1024) gA *=16, printf("%X",gA),gA -= (int)gA;
 d+=6,Co = 0;}

runtime = 8,06 secondes sur un Intel Quad Core


C'est le golf de code. Essayez de compresser votre code autant que possible en utilisant des noms de variables courts et en évitant les espaces. Par exemple, vous pouvez enregistrer de nombreux caractères en utilisant à la printf("%X",(int)gA)place de cette longue liste.
FUZxxl

1

PARI / GP - 40 octets

Cette version «triche» en utilisant \xpour afficher les chiffres hexadécimaux du résultat.

\p8197
x=Pi<<4^6;x-=x\1;x=(x<<4^6)\1
\xx

Cette version prend 87 octets pour se convertir en hexadécimal de la manière habituelle.

\p8197
x=Pi<<4^6;x-=x\1;concat([Vec("0123456789abcdef")[n+1]|n<-digits((x<<4^6)\1,16)])

Les deux versions fonctionnent en une petite fraction de seconde.


1

Perl - 59

use ntheory"Pi";say substr int(Pi(3000)<<8192)->as_hex,1027

Moins de 0,1 s.


0

Coquille 68

outils: bc -l, tr, cut

echo "scale=2468;obase=16;4*a(1)"|bc -l|tr -d '\\\n'|cut -c1027-2051

Shell 64, outils: bc -l, tr, tail, diffère par l'arrondi de la dernière place

echo "scale=2466;obase=16;4*a(1)"|bc -l|tr -d '\\\n'|tail -c1024

Pourrait être considéré comme de la triche, car la connaissance de la façon de calculer PI est en 4 * a (1), et que 1 doit utiliser l'échelle = 2466 a été étudiée de manière itérative.

Merci à breadbox pour l'idée d'utiliser cut.


Je ne vois pas comment cela pourrait être considéré comme de la triche; les chiffres sont calculés lors de l'exécution. Bien que je devrais noter que lorsque je l'exécute, sa sortie diffère sur le dernier chiffre (7 au lieu de A). BTW, je pense que vous pouvez remplacer la ddcommande par tail -c1024pour enregistrer quelques caractères.
boîte à pain

Oui, j'ai aussi observé la différence (et j'y ai passé une demi-heure :)). Si je dis à bc d'utiliser une échelle de x chiffres, il arrondit à ce chiffre en mode décimal et effectue ensuite la conversion hexadécimale. Donc, si je prends un chiffre de plus, cela produit un 69, pas un 7. Cependant - le style d'arrondi ou la troncature n'était pas spécifié dans la question. Et merci pour l'idée de queue. :)
utilisateur inconnu

La question spécifie: terminer et produire une sortie identique à ce qui est spécifié.
FUZxxl

@FUZxxl: "devrait ...", pas "doit ..." - Je pensais que cela devrait être une aide pour vérifier si la conversion hexadécimale fonctionne bien et le nombre de caractères à ignorer, pas dans le cadre de la spécification , pour se conformer au dernier chiffre de 1024. Mais j'ai cédé et ajouté 16 caractères pour en remplacer un.
utilisateur inconnu

1
Étant donné que la phrase commence par le mot «formellement», je conviens que le PO signifiait probablement cela dans le sens RFC du mot. De plus, vous pouvez toujours améliorer votre nouvelle solution en remplaçant l'utilisation de ddavec cut -c1027-2051. (Le shell possède de nombreux outils pour manipuler les flux de texte.)
breadbox
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.