Tính các chữ số của Pi


15

Đây là một nhiệm vụ hơi khác. Tính toán 1024 chữ số thập lục phân của số thập phân, bắt đầu tại vị trí thập lục phân thứ 1024.

Chính thức: Chương trình của bạn sẽ hoàn thành sau ít hơn 1 phút và tạo đầu ra sau:

25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5ebd09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd23876053317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbca58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e89a0do

Chương trình có thời lượng ngắn nhất sẽ thắng. Bạn phải tính toán tất cả các chữ số khi chạy. Bạn không phải thực hiện thuật toán tính toán π; nếu ngôn ngữ của bạn đã cung cấp chức năng đó, bạn có thể sử dụng nó.


Hah, nên dễ dàng. (+1, vẫn) Tôi cá là tôi có thể khiến nó thực thi trong vòng chưa đầy vài giây.
Mateen Ulhaq

@muntoo: Và? Giải pháp của bạn ở đâu?
FUZxxl

Tôi quên làm điều đó. :) BTW, tốc độ! = Code-golf.
Mateen Ulhaq

@muntoo: Tôi biết. Nhưng tôi cũng nghĩ rằng, 5 ngày là thời điểm tốt cho một nhiệm vụ dễ dàng như vậy.
FUZxxl

Câu trả lời:


13

Hiền nhân, 29 char

Đây không phải là gian lận về mặt kỹ thuật, vì các chữ số được tính khi chạy. Điều đó nói rằng, nó vẫn rẻ như địa ngục.

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

1
Chắc chắn không gian lận.
FUZxxl

11
Mmmm, sàn pi.
hộp bánh mì

13

Tiện ích Shell: 48

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

  • Tất cả đầu ra được "tính toán" khi chạy. (nhờ OP đăng giải pháp)
  • Chạy trong dưới một phút. (có thể phụ thuộc vào tốc độ kết nối internet của bạn)

Thông thường tôi downvote loại giải pháp đó, bởi vì chúng là một sự lạm dụng phổ biến của các quy tắc và không còn buồn cười. Nhưng chỉ vì bạn quá lén lút lấy giải pháp tham chiếu được cung cấp và ghi Tất cả đầu ra được "tính toán" khi chạy. (nhờ OP đăng giải pháp) , tôi cung cấp cho bạn một upvote;)
FUZxxl

Phiên bản chơi gôn: curl -sL ow.ly/shKGY|grep -Po \\w{99,}(37). Hoạt động trong Dash. Bash sẽ cần một byte bổ sung.
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

Sử dụng công thức BBP.

Liệu KHÔNG chạy ở dưới một phút (nhưng chúng tôi có một câu trả lời J: p)

Ví dụ cho 104 chữ số đầu tiên của số pi (cái này chạy nhanh):

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

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89
452821e638d01377be5466cf34e90c6cc0ac29b7

Tại sao bạn không sử dụng #: để ​​chuyển đổi các số thành thập lục phân?
FUZxxl

Tôi không chắc ý của bạn là gì. #:sẽ không xuất ra các chữ số hex.
Eelvex

IMHO dễ sử dụng #: và định hình lại để tạo các chữ số hex hơn phương pháp hiện tại của bạn.
FUZxxl

Ý bạn là gì (... 16 #:) Pi? Tôi nghĩ rằng chúng tôi không có đủ chữ số nên chúng tôi phải tạo ra chúng.
Eelvex

1
BTW, tôi phát hiện ra rằng có động từ hfdđể chuyển đổi số thành thập lục phân.
FUZxxl

5

JavaScript, 536

(Ngắt dòng và thụt chỉ cho mức độ dễ đọc)

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

Mất khoảng 25 giây, trên Google Chrome 14 trên lap-top của tôi bằng lõi Intel i5. Ai đó có thể đánh golf mã này? Tôi không thể chơi golf tốt .. :(

Dưới đây là không chơi gôn. Tôi chỉ loại bỏ tất cả các ý kiến ​​và thay đổi cho vòng lặp để chơi golf.

Đừng đề cập đến for(;s>=b;s-=b);s*=16;. Tôi đã thay đổi nó thành 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: Loại bỏ chức năng hoàn toàn không sử dụng. (Tại sao tôi giữ điều đó ?:)

Tái bút 100 chữ số đầu tiên của PI

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be5466cf34e90c6cc0ab


@FUZxxl: Mã không phải là golf không đủ? .. :(
JiminP

Nó đã thực sự. Nhưng IMHO có vẻ tốt hơn, nếu bạn sử dụng định dạng mã thay vì sử dụng cú pháp backtick. Như tôi đã viết, hãy thoải mái hoàn nguyên nếu bạn không thích.
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

Đó thực sự là tất cả các tối ưu hóa vi mô, mặc dù một số trong số chúng trông khá lớn. Tiết kiệm lớn nhất đến từ việc loại bỏ hai chức năng ẩn danh ở giữa có _lợi cho ,nhà điều hành. Cái khó nhất là hợp nhất $gthành một hàm, với một đối số tùy chọn để chọn giữa chúng. functionreturncả hai đều khá đắt đỏ, vì vậy một if(f)...elsevà một vài ,1là một sự đánh đổi hợp lý.
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;);

Giải pháp này tính toán tất cả số pi lên tới 2048 chữ số hex, bốn chữ số hex cùng một lúc và đưa ra nửa cuối của chúng. Thời gian thực hiện ít hơn 5 giây. Công thức được sử dụng để tính toán như sau:

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

Độ chính xác thu được lưu trữ phần còn lại trong một mảng và tiếp tục tăng từng phần trong 2 ^ 14.

Python 64 byte

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

Phương pháp tương tự như trên. Chạy trong khoảng 0,2 giây.

Hoặc là một lớp lót trong 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))))

Sử dụng công thức Bailey Nhận Borwein bào Plouffe (tất nhiên).

Chạy trong tốt dưới một phút.


3

Mã 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;}

thời gian chạy = 8,06 giây trên lõi Quad intel


Đây là mã golf. Cố gắng nén mã của bạn càng nhiều càng tốt bằng cách sử dụng tên biến ngắn và tránh khoảng trắng. Chẳng hạn, bạn có thể tiết kiệm rất nhiều ký tự bằng cách sử dụng printf("%X",(int)gA)thay vì danh sách dài đó.
FUZxxl

1

PARI / GP - 40 byte

Phiên bản này 'gian lận' bằng cách sử dụng \xđể hiển thị các chữ số thập lục phân của kết quả.

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

Phiên bản này mất 87 byte để chuyển đổi thành thập lục phân theo cách thông thường.

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

Cả hai phiên bản chạy trong một phần nhỏ của một giây.


1

Perl - 59

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

Ít hơn 0,1s.


0

Vỏ 68

dụng cụ: bc -l, tr, cắt

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

Shell 64, công cụ: bc -l, tr, đuôi, khác nhau trong cách làm tròn vị trí cuối cùng

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

Có thể bị coi là gian lận, vì kiến ​​thức về cách tính PI nằm trong 4 * a (1) và 1 phải sử dụng thang đo = 2466 đã được điều tra lặp đi lặp lại.

Nhờ Breadbox cho ý tưởng sử dụng cắt.


Tôi không thấy làm thế nào nó có thể được coi là gian lận; các chữ số được tính toán trong thời gian chạy. Mặc dù tôi nên lưu ý rằng khi tôi chạy nó, nó xuất ra khác với chữ số cuối (7 thay vì A). BTW, tôi nghĩ rằng bạn có thể thay thế ddlệnh bằng tail -c1024để lưu một vài ký tự.
hộp bánh mì

Vâng, tôi cũng đã quan sát sự khác biệt (và dành nửa giờ cho nó :)). Nếu tôi bảo bc sử dụng thang đo x chữ số, nó sẽ làm tròn đến chữ số đó ở chế độ thập phân và sau đó chuyển đổi hex. Vì vậy, nếu tôi lấy thêm một chữ số, nó sẽ tạo ra 69, chứ không phải 7. Tuy nhiên - kiểu làm tròn hoặc cắt bớt không được chỉ định trong câu hỏi. Và cảm ơn cho ý tưởng đuôi. :)
người dùng không xác định

Câu hỏi chỉ định: chấm dứt và tạo ra một đầu ra giống hệt với những gì được chỉ định.
FUZxxl

@FUZxxl: "nên ...", không phải "phải ..." - Tôi nghĩ rằng nó nên giúp kiểm tra xem liệu chuyển đổi hex có hoạt động tốt không và số lượng ký tự bỏ qua, không phải là một phần của thông số kỹ thuật , để phù hợp với chữ số cuối cùng của 1024. Nhưng tôi đã đưa ra và thêm 16 ký tự để thay thế một chữ số.
người dùng không xác định

1
Cho rằng câu bắt đầu bằng từ "Chính thức", tôi đồng ý rằng OP có thể có nghĩa theo nghĩa RFC của từ này. Ngoài ra, bạn vẫn có thể cải thiện giải pháp mới của mình bằng cách thay thế việc sử dụng ddbằng cut -c1027-2051. (Shell có nhiều công cụ để thao tác các luồng văn bản.)
Breadbox
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.