精确传输Pi ...


11

Pi的蒙特卡洛估计器之后,这一挑战是为常数Pi生成最短的代码。除了此处,您的代码必须永远输出pi的连续数字。

这是代码高尔夫,因此最短的提交(以字节为单位)获胜,只是它必须在合理的PC上在不到10秒的时间内输出前10,000位数字,并且永远不能终止。

Pi或Trig函数不能使用任何内置函数。


删除了对代码大小的硬限制。


1
tweetable表示您的代码必须少于140个字符?
Ypnypn

5
没有字符限制,问题本身似乎具有挑战性。
BobTheAwesome

1
@BobTheAwesome通过受欢迎的需求删除了字符限制。

1
@ mbomb007一点也不明显,必须打印小数点,或者数字不能用空格分隔。挑战仅在于“输出pi的连续数字”。小数点不是数字。3141...是-pi的连续数字。
orlp

1
最好将输出的数字设置为Pi,以便数字之间没有空格。如果包含小数点,那就更好了。

Answers:


7

果酱-48

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

这会以越来越高的精度将π计算为2 * sum(k!/(2k + 1)!!),并且在每一步都从其中断处打印出一堆数字。

您可以在线尝试仅执行8次(外循环)迭代并输出512位数字的修改版本,或者将Java解释器用于真实内容。在我的笔记本电脑上,它在6秒钟内达到了16384位数字。

注意:该程序非常耗内存;表现较好但稍长的版本是:

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

说明:

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个字节

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

http://www.cs.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf的实现。


在5分钟之前击败我……
.:

这很棒。但是,我希望所有数字都在同一行。换句话说,输出看起来像Pi。

2
@Lembik我更改了答案-更长了7个字节,但现在都在一行上了。
Orlp

5

GolfScript(81个字符)

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

在线演示(比合理的台式机慢得多,并且进行了微小的代码更改以循环有限的次数)。

当然,我使用了我在先前的评论中提到的自锁算法,但是花了我一段时间才使它满意。Gibbons的论文中提出的算法是(伪代码)

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等效于(伪代码)

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
}

这样可以在初始化和堆栈管理中节省一些字符。


4

Pyth- 87 85字节

http://www.cs.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf的另一种翻译。我本来打算做Python,但是@orlp击败了我,所以我做了Pyth。足够小以适合推文。

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

由于来自end=""打印设置的打印缓冲区,它以间歇性步骤将输出提供给stdout 。由于规范显示“连续数字”,因此我目前不打印小数点。它的任务正在杀死我的分数。

=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

在这里尝试。(注意:由于在线解释器仅给出完整的结果,因此无限循环已结束,因此仅打印前100个,这会增加代码大小。要尝试无限循环,请下载本地解释器。)

定时

在我的Google云端计算微型实例上,根据花费的总时间:real: 0m2.062s这样显然足够快。


3

Scala,599字节

下面的代码直接来自Pi数字的Spigot算法的附录2中的Pascal代码。显然,几乎没有打高尔夫球。该代码的确会在10秒内生成10,000位数字,piSpigot(10000)并且如果有一个无限内存,则可以对其进行参数化以生成很多数字,但不是无限。我不确定这是否满足问题限制,因此请提供反馈。

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
我认为无限产生数字的要求意味着您需要使用一种流算法,而不是一种采用参数的算法n。参见例如cs.ox.ac.uk/people/jeremy.gibbons/publications/spigot.pdf
Peter Taylor

无限的记忆和无限的时间应该赋予无限的位数。

1

Befunge-98(PyFunge),120字节

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<

在线尝试!

就时间限制而言,这是临界点。10,000位数在我的笔记本电脑上花费11秒钟左右,但是我确定必须有一台“合理的” PC,它的处理速度比这更快。

但是,如果您要在TIO上进行尝试,请注意,直到达到60秒的时间限制,它才会返回任何内容,因为该算法旨在永久运行。到那时,您将拥有超过10,000位数。

我正在使用Jeremy Gibbons插口算法,我认为它与此处的大多数其他答案相同。但是,请注意,这依赖于具有任意精度存储单元的解释器,而我知道支持的唯一实现是PyFunge

说明

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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.