Hitung digit Pi


15

Ini adalah tugas yang agak berbeda. Hitung 1024 digit heksadesimal π, dimulai dari tempat heksadesimal 1024.

Secara formal: Program Anda harus selesai dalam waktu kurang dari 1 menit dan menghasilkan output berikut:

25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5ebd09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd23876053317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbca58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e89a0d6411bd3ae1e7e4900250e2d2071b35e226800bb57b8e0af2464369bf009b91e5563911d59dfa6aa78c14389d95a537f207d5ba202e5b9c5832603766295bob

Program dengan kemenangan terpendek terpendek. Anda harus menghitung semua digit saat runtime. Anda tidak harus mengimplementasikan algoritma yang menghitung π; jika bahasa Anda sudah menyediakan fungsionalitas itu, Anda dapat menggunakannya.


Hah, seharusnya mudah. (+1, tetap) Saya yakin saya bisa mengeksekusinya dalam waktu kurang dari beberapa detik.
Mateen Ulhaq

@muntoo: Dan? Di mana solusinya?
FUZxxl

Saya lupa melakukannya. :) BTW, kecepatan! = Kode-golf.
Mateen Ulhaq

@muntoo: Saya tahu. Tetapi saya juga berpikir, bahwa 5 hari adalah waktu yang tepat untuk tugas yang mudah.
FUZxxl

Jawaban:


13

Sage, 29 char

Ini tidak curang secara teknis, karena angka dihitung pada saat runtime. Yang mengatakan, itu masih murah sekali.

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

1
Jelas tidak curang.
FUZxxl

11
Mmmm, pi lantai.
kotak roti

13

Shell Utilities: 48

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

  • Semua output "dihitung" pada saat runtime. (terima kasih kepada OP yang memposting solusinya)
  • Berjalan kurang dari satu menit. (mungkin tergantung pada kecepatan koneksi internet Anda)

Biasanya saya downvote solusi semacam itu, karena mereka adalah penyalahgunaan aturan umum dan tidak lagi lucu. Tetapi hanya karena Anda sangat licik untuk mengambil solusi referensi yang disediakan dan menulis Semua output "dihitung" saat runtime. (terima kasih kepada OP yang memposting solusinya) , saya memberi Anda upvote;)
FUZxxl

Versi golf: curl -sL ow.ly/shKGY|grep -Po \\w{99,}(37). Bekerja di Dash. Bash akan membutuhkan byte tambahan.
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

Menggunakan formula BBP.

Apakah tidak berjalan di bawah satu menit (tapi kami memiliki jawaban J: p)

Contoh untuk 104 digit pertama π (ini berjalan cepat):

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

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89
452821e638d01377be5466cf34e90c6cc0ac29b7

Mengapa Anda tidak menggunakan #: untuk mengonversi angka menjadi heksadesimal?
FUZxxl

Saya tidak yakin apa yang Anda maksud. #:tidak akan menampilkan digit hex.
Eelvex

IMHO lebih mudah menggunakan #: dan membentuk kembali untuk menghasilkan hex-digit daripada pendekatan Anda saat ini.
FUZxxl

Maksudmu sesuatu seperti (... 16 #:) Pi? Saya pikir kita tidak memiliki angka yang cukup sehingga kita harus menghasilkannya.
Eelvex

1
BTW, saya menemukan bahwa ada kata kerja hfduntuk mengubah angka menjadi heksadesimal.
FUZxxl

5

JavaScript, 536

(Linebreak dan indentasi hanya untuk keterbacaan)

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))

Dibutuhkan sekitar 25 detik, di Google Chrome 14 pada putaran atas saya menggunakan Intel i5 core. Bisakah orang lain menggunakan kode ini? Saya tidak bisa bermain golf dengan baik .. :(

Di bawah ini bukan golf. Saya hanya menghapus semua komentar dan berubah untuk loop ke golf.

Jangan menyebutkan tentang for(;s>=b;s-=b);s*=16;. Saya mengubahnya menjadi 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: Dihapus fungsi yang sama sekali tidak digunakan. (Kenapa saya menyimpannya?: /)

PS. 100 digit pertama PI

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be5466cf34e90c6cc0ab


@ FuZxxl: Apakah kode non-golf tidak cukup? .. :(
JiminP

Memang benar. Tapi IMHO itu terlihat lebih baik, jika Anda menggunakan pemformatan kode daripada menggunakan sintaks backtick. Seperti yang saya tulis, jangan ragu untuk kembali jika Anda tidak suka.
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

Itu benar-benar optimasi mikro, meskipun beberapa di antaranya terlihat cukup besar. Penghematan terbesar berasal dari menghilangkan dua fungsi anonim di tengah _mendukung ,operator. Yang paling sulit adalah penggabungan $dan gke dalam satu fungsi, dengan argumen opsional untuk memilih di antara mereka. functiondan returnkeduanya cukup mahal, jadi if(f)...elsedan beberapa ,1adalah tradeoff yang masuk akal.
Peter Taylor

4

PHP 116 114 byte

<?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;);

Solusi ini menghitung semua pi hingga 2048 digit hex, empat digit hex sekaligus, dan menampilkan setengahnya. Waktu eksekusi kurang dari 5 detik. Rumus yang digunakan untuk perhitungan adalah sebagai berikut:

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

Presisi diperoleh dengan menyimpan sisanya dalam array, dan melanjutkan setiap divisi 2 ^ 14 secara bertahap.

Python 64 byte

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

Metode yang sama seperti di atas. Berjalan sekitar 0,2 detik.

Atau sebagai one-liner dalam 73 byte :

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))))

Menggunakan rumus Bailey – Borwein – Plouffe (tentu saja).

Berjalan dengan baik di bawah satu menit.


3

Kode 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 detik pada intel Quad core


Ini golf kode. Cobalah untuk mengompres kode Anda sebanyak mungkin dengan menggunakan nama variabel pendek dan menghindari spasi. Misalnya, Anda bisa menyimpan banyak karakter dengan menggunakan printf("%X",(int)gA)daftar panjang itu.
FUZxxl

1

PARI / GP - 40 byte

Versi ini 'menipu' dengan menggunakan \xuntuk menampilkan digit heksadesimal dari hasil.

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

Versi ini membutuhkan 87 byte untuk dikonversi menjadi heksadesimal dengan cara biasa.

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

Kedua versi berjalan dalam sepersekian detik.


1

Perl - 59

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

Kurang dari 0,1.


0

Shell 68

alat: bc -l, tr, cut

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

Shell 64, alat: bc-l, tr, tail, berbeda dalam pembulatan tempat terakhir

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

Mungkin dianggap curang, karena pengetahuan bagaimana menghitung PI ada pada 4 * a (1), dan bahwa saya harus menggunakan skala = 2466 diselidiki secara iteratif.

Terima kasih kepada kotak roti untuk ide menggunakan cut.


Saya tidak melihat bagaimana itu bisa dianggap curang; digit dihitung pada saat runtime. Meskipun saya harus mencatat bahwa ketika saya menjalankannya, outputnya berbeda pada digit terakhir (7 bukannya A). BTW, saya pikir Anda dapat mengganti ddperintah dengan tail -c1024untuk menyimpan beberapa karakter.
kotak roti

Ya, saya mengamati perbedaannya juga (dan menghabiskan setengah jam untuk itu :)). Jika saya memberi tahu bc untuk menggunakan skala x digit, angka itu membulatkan ke angka itu dalam mode desimal, dan melakukan konversi hex sesudahnya. Jadi jika saya mengambil satu digit lagi, itu menghasilkan angka 69, bukan angka 7. Namun - gaya pembulatan atau pemotongan tidak ditentukan dalam pertanyaan. Dan terima kasih atas ide buntutnya. :)
pengguna tidak diketahui

Pertanyaannya menentukan: mengakhiri dan menghasilkan output yang identik dengan apa yang ditentukan.
FUZxxl

@ FuZxxl: "harus ...", bukan "harus ..." - Saya pikir ini harus membantu untuk memeriksa, apakah konversi hex berjalan dengan baik, dan jumlah karakter yang dilewati, bukan sebagai bagian dari spesifikasi , agar sesuai dengan digit terakhir 1024. Tapi saya menyerah dan menambahkan 16 karakter untuk menggantikannya.
pengguna tidak diketahui

1
Mengingat bahwa kalimat dimulai dengan kata "Secara formal", saya akan setuju bahwa OP mungkin berarti dalam arti kata RFC . Selain itu, Anda masih dapat meningkatkan solusi baru dengan mengganti penggunaan dddengan cut -c1027-2051. (Shell memiliki banyak alat untuk memanipulasi aliran teks.)
kotak roti
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.