Transmitir Pi ... precisamente

11

Seguindo o estimador de Pi de Monte Carlo, este desafio é produzir o código mais curto para o Pi constante. Exceto aqui, seu código deve gerar dígitos consecutivos de pi para sempre.

Este é um código de código, portanto, o envio mais curto (em bytes) vence, exceto que ele deve gerar os primeiros 10.000 dígitos em menos de 10 segundos em um PC razoável e nunca deve terminar.

Você não pode usar nenhuma função interna para funções Pi ou trigonométricas.


Removido o limite rígido no tamanho do código.

Comunidade
fonte
1
Por tweetable, você quer dizer que o código deve ter menos de 140 caracteres?
Ypnypn 15/03
5
O problema em si parece desafiador sem a limitação de caracteres.
BobTheAwesome
1
@BobTheAwesome Removido o limite de caracteres pela demanda popular.
1
@ mbomb007 Não é óbvio que o ponto decimal deva ser impresso ou que os dígitos não possam ser separados por espaços em branco. O desafio é apenas "gerar dígitos consecutivos de pi". O ponto decimal não é um dígito. 3141...é isso - dígitos consecutivos de pi.
orlp
1
Seria melhor se o número impresso fosse Pi, para que não houvesse espaço entre os dígitos, por exemplo. Seria ainda melhor se incluísse o ponto decimal.

Respostas:

7

CJam - 48

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

Isso calcula π como 2 * soma (k! / (2k + 1) !!) com uma precisão cada vez maior e a cada passo imprime um monte de dígitos de onde parou.

Você pode experimentar on - line uma versão modificada que realiza apenas 8 iterações (loop externo) e imprime 512 dígitos, ou pode usar o interpretador java para real. No meu laptop, ele chega a 16384 dígitos em cerca de 6 segundos.

Nota: este programa consome muita memória; uma versão melhor comportada, mas um pouco mais longa é:

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

Explicação:

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
aditsu sair porque SE é MAU
fonte
8

Python, 138 bytes

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

Implementação de http://www.cs.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf .

orlp
fonte
Bata-me a ele por 5 minutos ..... :)
Maltysen
Isso é ótimo. No entanto, eu esperava que todos os dígitos estivessem em uma linha. Em outras palavras, que a saída se pareceria com Pi.
2
@ Lembik mudei minha resposta - 7 bytes a mais, mas agora tudo em uma linha.
orlp 16/03/2015
5

GolfScript (81 caracteres)

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

Demonstração on-line (que é muito mais lenta que uma área de trabalho razoável e possui alterações triviais no código para repetir um número finito de vezes).

Obviamente, usei o algoritmo de torneira que mencionei em um comentário anterior, mas demorei um pouco para jogar com satisfação. O algoritmo apresentado no artigo de Gibbons é (pseudocódigo)

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
}

O GolfScript acima é equivalente a (pseudocódigo)

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
}

que salva alguns caracteres na inicialização e no gerenciamento de pilhas.

Peter Taylor
fonte
4

Pitão - 87 85 bytes

Outra tradução de http://www.cs.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf . Eu ia fazer Python, mas @orlp me venceu, então eu fiz Pyth. Pequeno o suficiente para caber em um tweet.

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

Ele fornece saída para stdout, embora em etapas intermitentes, devido ao buffer de impressão resultante da configuração end=""na impressão. Atualmente, não imprimo o ponto decimal, pois a especificação indica "dígitos consecutivos". São as tarefas que estão matando minha pontuação.

=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

Experimente aqui . (Nota: Como o intérprete on-line fornece apenas resultados completos, o loop infinito é desativado; portanto, ele imprime apenas os 100 primeiros, o que aumenta o tamanho do código. Para testar o infinito, faça o download do intérprete local.)

Cronometragem

Na minha instância da computação no Google Cloud, de acordo com o tempo que o GNU levou: real: 0m2.062sé obviamente rápido o suficiente.

Maltysen
fonte
3

Scala, 599 bytes

O código abaixo é uma porta reta do código Pascal do Apêndice 2 do A Algoritmo de torneira para os dígitos do Pi . Claramente, muito pouco golfe ainda foi feito. O código gera 10.000 dígitos em menos de 10 segundos piSpigot(10000)e, se houver memória infinita, pode ser parametrizado para gerar muitos dígitos, mas não infinitos. Não tenho certeza se isso está atendendo às restrições do problema, portanto, forneça feedback.

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)
Dave Swartz
fonte
5
Eu acho que o requisito para produzir dígitos ad infinitum significa que você precisa usar um algoritmo de streaming em vez de um que aceita um parâmetro n. Veja, por exemplo, cs.ox.ac.uk/people/jeremy.gibbons/publications/spigot.pdf
Peter Taylor
Memória infinita e tempo infinito devem fornecer um número infinito de dígitos.
1

Befunge-98 (PyFunge), 120 bytes

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<

Experimente online!

Isso é limítrofe em termos de prazo. 10.000 dígitos levam cerca de 11 segundos no meu laptop, mas tenho certeza de que deve haver um PC "razoável" que possa fazê-lo mais rápido que isso.

No entanto, se você estiver testando no TIO, observe que ele não retornará nada até atingir o limite de 60 segundos, pois o algoritmo foi projetado para continuar para sempre. A essa altura, você terá mais de 10.000 dígitos.

Estou usando o algoritmo de torneira Jeremy Gibbons, que acho que é o mesmo que a maioria das outras respostas aqui. No entanto, observe que isso depende do intérprete ter células de memória de precisão arbitrárias, e a única implementação que eu conheço que suporta isso é o PyFunge .

Explicação

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.
James Holderness
fonte