Truyền Pi chính xác


11

Tiếp theo từ công cụ ước tính Pi của Monte Carlo, thách thức này là tạo ra mã ngắn nhất cho hằng số Pi. Ngoại trừ ở đây mã của bạn phải xuất ra các chữ số liên tiếp của pi mãi mãi.

Đây là mã golf, do đó, lần gửi ngắn nhất (tính bằng byte) ngoại trừ việc nó phải xuất 10.000 chữ số đầu tiên trong vòng chưa đầy 10 giây trên một PC hợp lý và nó không bao giờ phải chấm dứt.

Bạn không thể sử dụng bất kỳ chức năng tích hợp nào cho các chức năng Pi hoặc trig.


Đã xóa giới hạn cứng về kích thước mã.


1
Theo tweet, bạn có nghĩa là mã phải ít hơn 140 ký tự?
Ypnypn 15/03/2015

5
Vấn đề tự nó có vẻ thách thức mà không có giới hạn nhân vật.
BobTheAwgie 15/03/2015

1
@BobTheAwgie Xóa giới hạn ký tự theo yêu cầu phổ biến.

1
@ mbomb007 Hoàn toàn không rõ ràng rằng dấu thập phân phải được in hoặc các chữ số có thể không được phân tách bằng khoảng trắng. Thách thức chỉ đơn thuần là "xuất ra các chữ số liên tiếp của pi". Dấu chấm thập phân không phải là một chữ số. 3141...là - các chữ số liên tiếp của pi.
orlp

1
Sẽ là tốt nhất nếu số được in ra là Pi để không có khoảng cách giữa các chữ số chẳng hạn. Sẽ tốt hơn nữa nếu bao gồm dấu thập phân.

Câu trả lời:


7

CJam - 48

3.1o{1YAZ2*:Z#*{_2$*2$2*)/@)\}h*]:+sX2*:X>X<o1}g

Điều này tính toán π là 2 * tổng (k! / (2k + 1) !!) với độ chính xác cao hơn và lớn hơn và ở mỗi bước sẽ in một loạt các chữ số từ nơi nó rời đi.

Bạn có thể thử trực tuyến một phiên bản sửa đổi chỉ thực hiện 8 lần lặp (vòng ngoài) và in 512 chữ số hoặc sử dụng trình thông dịch java cho thực tế. Trên máy tính xách tay của tôi, nó có tới 16384 chữ số trong khoảng 6 giây.

Lưu ý: chương trình này rất đói bộ nhớ; một phiên bản tốt hơn nhưng dài hơn một chút là:

3.1o{T2AZ2*:Z#*1{@2$+@2$*2$2*)/@)1$}g;;sX2*:X>X<o1}g

Giải trình:

3.1o              print 3.1
{…1}g             repeat indefinitely
    1YA           push 1, 2 and 10 (Y=2, A=10)
    Z2*:Z         push Z*2 (Z=3 initially) and store back in Z
    #*            calculate 2*10^Z (2 from the formula and 10^Z for precision)
                  this is the term for k=0, and the earlier 1 represents k
    {…}h          do-while
                  at each iteration, the stack contains: terms, k, last-term
        _2$*      copy the previous term and k and multiply them
        2$2*)/    divide the previous number by 2*k+1
                  this is the current term of the series
        @)\       increment k and move it before the current term
                  the current term now serves as the loop condition
                  so the loop terminates when the term becomes 0
    *             multiply k and the last term (0), to get rid of k
    ]:+s          put all the terms in an array, add them and convert to string
                  we obtain an approximation of π*10^Z
    X2*:X         push X*2 (X=1 initially) and store back in X
    >X<o          print X digits starting from the X position

8

Python, 138 byte

q,r,t,i=1,180,60,2
while 1:u,y=27*i*(i+1)+6,(q*(27*i-12)+5*r)//(5*t);print(y,end="");q,r,t,i=10*q*i*(2*i-1),10*u*(q*(5*i-2)+r-y*t),t*u,i+1

Triển khai http://www.cs.ox.ac.uk/jeremy.g Ribbon / publications / spigot.pdf .


Đánh bại tôi vào nó bằng cách 5 phút ..... :)
Maltysen

Điều đó thật tuyệt. Tuy nhiên tôi đã hy vọng tất cả các chữ số sẽ nằm trên một dòng. Nói cách khác, đầu ra sẽ giống như Pi.

2
@Lembik Tôi đã thay đổi câu trả lời của mình - dài hơn 7 byte, nhưng giờ tất cả chỉ trên một dòng.
orlp

5

GolfScript (81 ký tự)

1:i:^3{3i):i*(.(*3*.@*.5*3$27i*12-*+@^*:^5*/.print^*2$5i*2-*--\10*i*2i*(*\10*.}do

Bản demo trực tuyến (chậm hơn nhiều so với máy tính để bàn hợp lý và có các thay đổi mã nhỏ để lặp một số lần hữu hạn).

Tất nhiên, tôi đã sử dụng thuật toán spigot mà tôi đã đề cập trong một nhận xét trước đó, nhưng tôi phải mất một thời gian để đánh golf nó để tôi hài lòng. Thuật toán như được trình bày trong bài báo của Gibbons là (mã giả)

q = 1; r = 180; t = 60; i = 2
while (true) {
    u = 3*(3*i+1)*(3*i+2)
    y = (q*(27*i-12)+5*r) / (5*t)
    print y
    r += q*(5*i-2)-y*t
    r *= 10*u
    q *= 10*i*(2*i-1)
    t *= u
    i += 1
}

GolfScript ở trên tương đương với (mã giả)

t = i = q = 1; r = 3
while (true) {
    u = 3*(3*i+1)*(3*i+2)
    i += 1
    r *= u
    t *= u
    y = (q*(27*i-12)+5*r) / (5*t)
    print y
    r -= y*t - q*(5*i-2)
    q *= 10*i*(2*i-1)
    r *= 10
}

trong đó lưu một số ký tự trong khởi tạo và trong quản lý ngăn xếp.


4

Pyth - 87 85 byte

Một bản dịch khác của http://www.cs.ox.ac.uk/jeremy.g Ribbon / publications / spigot.pdf . Tôi sẽ làm Python nhưng @orlp đã đánh bại tôi, vì vậy tôi đã làm Pyth. Đủ nhỏ để phù hợp với một tweet.

=H3=d1=bd=Gd#K+**hb27b6~b1=H*HK=d*dKJ/+*-*27b12G*5H*5d=H*T-H-*Jd*-*5b2G=G***GTbtybpkJ

Nó cung cấp đầu ra cho thiết bị xuất chuẩn, mặc dù trong các bước không liên tục vì bộ đệm in xuất phát từ cài đặt end=""trong in. Tôi hiện không in dấu thập phân vì thông số kỹ thuật nói "các chữ số liên tiếp". Đó là bài tập đang giết chết điểm số của tôi.

=H3                     Set H to 3
=d1                     Set d to 1
=bd                     Set b to d which is 1
=Gd                     Set G to d which is 1
#                       Infinte Loop
  K                     Set K to
    +**hb27b6           27*b*(b+1)+6
  ~b1                   b+=1
  =H*HK                 H*=K
  =d*dK                 d*=K
  J                     Set J to
    /                   Integer division
      +*-*27b12G*5H     G*(27*b-12)+5*H
      *5d               5*d
  =H                    Set H to
    *T-H-*Jd*-*5b2G     10*(H-(J*d -G*(5*b-2)))
  =G                    Set G to
    ***GTbtyb           G*10*b*(2*b-1)
  pkJ                   Print J with the end as "", not a newline

Hãy thử nó ở đây . (Lưu ý: Vì trình thông dịch trực tuyến chỉ cung cấp kết quả đã hoàn thành, vòng lặp vô hạn bị loại bỏ, do đó, nó chỉ in 100 đầu tiên làm tăng kích thước mã. Để thử vô hạn, hãy tải xuống trình thông dịch cục bộ.)

Thời gian

Trên google điện toán đám mây vi mô của tôi, theo thời gian gnu đã mất: real: 0m2.062svì vậy nó rõ ràng là đủ nhanh.


3

Scala, 599 byte

Mã dưới đây là một cổng thẳng của mã Pascal từ Phụ lục 2 của Thuật toán A Spigot cho các chữ số của Pi . Rõ ràng rất ít chơi golf đã được thực hiện. Mã này tạo ra 10.000 chữ số trong vòng dưới 10 giây piSpigot(10000)và nếu một người có bộ nhớ vô hạn có thể được tham số hóa để tạo ra nhiều chữ số, nhưng không phải là vô hạn. Tôi không chắc chắn nếu điều này đáp ứng các hạn chế vấn đề vì vậy xin vui lòng cung cấp thông tin phản hồi.

def piSpigot(n: Int): Unit = {
  val len=10*n/3
  var nines=0
  var predigit=0
  val a=Array.fill(len)(2)
  (1 to n).foreach {_=>
    var q=0
    (1 to n).reverse.foreach{i=>
      var x=10*a(i)+q*i
      a(i)=x%(2*i-1)
      q=x/(2*i-1)
    }
    a(1)=q%10
    q/=10
    if (q==9) {
      nines+=1
    } else if (q==10) {
      print(predigit+1)
      1.to(nines).foreach(_=>print(0))
      predigit=0
      nines=0
    } else {
      print(predigit)
      predigit=q
      if (nines!=0) {
        1.to(nines).foreach(_=>print(9))
        nines=0
      }
    }
  }
  println(predigit)
}
piSpigot(10000)

5
Tôi nghĩ rằng yêu cầu để tạo ra các chữ số ad infinitum có nghĩa là bạn cần sử dụng thuật toán phát trực tuyến thay vì thuật toán lấy tham số n. Xem ví dụ: cs.ox.ac.uk/people/jeremy.g Ribbon / publications / spigot.pdf
Peter Taylor

Bộ nhớ vô hạn và thời gian vô hạn sẽ cho vô số chữ số.

1

Befunge-98 (PyFunge), 120 byte

cf*10p'<20p11>00p1+:30p:::*+39**6+:30g39**c-00g*10gv
>:2*1-*00g*a*^
^:p02*g02p01*a*-*g02\+g01*g00-2*5g03,+*86:/*5g02+*5<

Hãy thử trực tuyến!

Đây là đường biên giới về mặt thời gian. 10.000 chữ số mất khoảng 11 giây trên máy tính xách tay của tôi, nhưng tôi chắc chắn phải có một PC "hợp lý" có thể làm điều đó nhanh hơn thế.

Tuy nhiên, nếu bạn đang dùng thử trên TIO, lưu ý rằng nó sẽ không trả lại bất cứ thứ gì cho đến khi đạt đến giới hạn thời gian 60 giây, vì thuật toán được thiết kế để tiếp tục tồn tại. Vào thời điểm đó, bạn sẽ có hơn 10.000 chữ số.

Tôi đang sử dụng thuật toán spigot Jeremy Gibbons, mà tôi nghĩ là giống như hầu hết các câu trả lời khác ở đây. Tuy nhiên, lưu ý rằng điều này phụ thuộc vào trình thông dịch có các ô nhớ chính xác tùy ý và cách thực hiện duy nhất tôi biết về sự hỗ trợ đó là PyFunge .

Giải trình

cf*10p                     Initialise r to 180.
      '<20p                Initialise t to 60.
           11              Initialise i and q on the stack to 1.

>                          Start of the main loop.
 00p                       Save the current value of q in memory.
    1+:30p                 Increment i and save a copy in memory.      
          :::*+39**6+      Calculate u = 27*(i*i+i)+6.
                     :     Make a duplicate, since we'll need two copies later.

       30g39**c-00g*10gv   Calculate y = (q*(27*i-12)+5*r)/(5*t).
              /*5g02+*5<
        ,+*86:             Convert y to a character so we can output it.

*a*-*g02\+g01*g00-2*5g03   Calculate r = 10*u*(q*(i*5-2)+r-y*t)

         p01               Save the updated r.
     *g02                  Calculate t = t*u
  p02                      Save the updated t.

>:2*1-*00g*a*              Calculate q = 10*q*i*(i*2-1).
^:
             ^             Return to the start of the main loop.
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.