Encontre o enésimo decimal de pi


33

Já existem 30 desafios dedicados a pi, mas nenhum pede que você encontre o n-ésimo decimal, então ...

Desafio

Para qualquer número inteiro no intervalo de 0 <= n <= 10000exibição, o enésimo decimal de pi.

Regras

  • Os decimais são todos os números após 3.
  • Seu programa pode ser uma função ou um programa completo
  • Você deve gerar o resultado na base 10
  • Você pode obter nde qualquer método de entrada adequado (stdin, input (), parâmetros de função, ...), mas não codificado
  • Você pode usar a indexação baseada em 1 se for nativa do seu idioma de escolha
  • Você não precisa lidar com entradas inválidas ( n == -1, n == 'a'ou n == 1.5)
  • Builtins são permitidos, se eles suportarem até pelo menos 10 mil decimais
  • O tempo de execução não importa, pois esse é o código mais curto e não o mais rápido
  • Este é o , o código mais curto em bytes ganha

Casos de teste

f(0)     == 1
f(1)     == 4 // for 1-indexed languages f(1) == 1
f(2)     == 1 // for 1-indexed languages f(2) == 4
f(3)     == 5
f(10)    == 8
f(100)   == 8
f(599)   == 2
f(760)   == 4
f(1000)  == 3
f(10000) == 5

Para referência, aqui estão os primeiros 100 mil dígitos de pi.


Built-ins? por exemplostr(pi())[n+2]
primo 04/07

6
Os destinos duplos mais próximos da IMO são a computação de dígitos truncados somando poderes de pi (sobrecarrega o parâmetro ou seria apenas uma diferença finita aplicada a esse desafio), transmitem pi com precisão (adiciona um índice e suprime algumas impressões) e criptografia de janelas Pi .
Peter Taylor

3
@Suever ofcourse! Essa regra é apenas para salientar que 10k é o mínimo que seu programa deve ser capaz de executar #
Bassdrop Cumberwubwubwub

4
Sugiro adicionar f (599) aos casos de teste, pois pode ser fácil cometer erros (você precisa de cerca de três casas decimais de precisão extra).
aditsu 04/07

2
Também é fácil arredondar incorretamente f (760) = 4, que inicia a sequência 4 999999 8.
Anders Kaseorg

Respostas:


22

05AB1E, 3 bytes

žs¤

Explicado

žs   # push pi to N digits
  ¤  # get last digit

Experimente online

Usa indexação baseada em 1.
Suporta até 100k dígitos.


Pi para n dígitos não arredondam?
busukxuan

7
@busukxuan No. Ele usou uma constante predefinida de pi para 100k dígitos e recupera N deles.
Emigna

4
@ Emigna Isso é muito útil. Boa solução.
Suever 04/07

2
Curto e Sharp, PCG no seu melhor
Xylius

16

Python 2, 66 bytes

n=input()+9
x=p=5L**7
while~-p:x=p/2*x/p+10**n;p-=2
print`x/5`[-9]

A entrada é retirada do stdin.


Uso da amostra

$ echo 10 | python pi-nth.py
8

$ echo 100 | python pi-nth.py
8

$ echo 1000 | python pi-nth.py
3

$ echo 10000 | python pi-nth.py
5

Tenha cuidado ao usar n no algoritmo ... de saída para 599 deve ser de 2, não 1. Além disso, você pode querer especificar que você está usando python 2.
aditsu

@aditsu updated. Confirmado para todos os n ≤ 1000 .
primo

1
Se você considera na entrada mais 9, pode evitar parênteses.
Xnor

@xnor d'oh. Obrigado;)
primo

2
Os primeiros dígitos gerados por esse algoritmo são '3.141596535897932…', que está faltando um '2' entre os pontos 5 e 6. Por que? Porque é quando o operador `` do Python 2 começa a acrescentar um Là string.
Anders Kaseorg

11

Bash + coreutils, 60 49 bytes

echo "scale=10100;4*a(1)"|bc -l|tr -d '\\\n'|cut -c$(($1+2))

bc -l<<<"scale=$1+9;4*a(1)-3"|tr -dc 0-9|cut -c$1

Melhorado por Dennis . Obrigado!

O índice é baseado em um.


11

Python 2, 73 71 73 bytes

obrigado a @aditsu por aumentar minha pontuação em 2 bytes

Finalmente, um algoritmo que pode ser concluído em menos de 2 segundos.

n=10**10010
a=p=2*n
i=1
while a:a=a*i/(2*i+1);p+=a;i+=1
lambda n:`p`[n+1]

Ideone it!

Usa a fórmula pi = 4*arctan(1)ao computar arctan(1)usando sua série taylor.


Muito rápido. A indexação 1 não é nativa do python. Da última vez que me lembro (é verdade que estou inativo há um tempo), havia consenso de que funções precisam ser definidas, por exemplo f=lambda n:....
primo

2
Quase todas as lambda aqui são anônimas (você pode procurar respostas em Python neste site) #
Leaky Nun

Meta post relevante . Parece estar em violação da Regra 1 e 3 (depois de executar seu código, não há nenhuma maneira de captar a referência de função; a definição da função que precisa ser digitado para cada entrada ( (lambda n:`p`[n+1])(1), (lambda n:`p`[n+1])(2)...).
primo

1
Você não pode executar o código diretamente. É semelhante a colocar importinstruções de antemão, apenas que isso faz algumas variáveis ​​globais de antemão.
Leaky Nun

i=3 while a:a=i/2*a/i;p+=a;i+=2para 4.
primo 04/07

7

MATL, 11 10 bytes

1 byte salvo graças a @Luis

YPiEY$GH+)

Esta solução utiliza indexação baseada em 1

Experimente Online

Todos os casos de teste

Explicação

YP  % Pre-defined literal for pi
iE  % Grab the input and multiply by 2 (to ensure we have enough digits to work with)
Y$  % Compute the first (iE) digits of pi and return as a string
G   % Grab the input again
H+  % Add 2 (to account for '3.') in the string
)   % And get the digit at that location
    % Implicitly display the result

@LuisMendo Oh sim, acho que a saída já é uma string. Doh!
Suever 04/07

@LuisMendo Oh, eu nunca pensei nisso. Eu sempre uso YPno meu teste da caixa de ferramentas simbólica
Suever

YP é realmente permitido? A questão diz que é permitido se ele suporta <= 10k dígitos
busukxuan

O @Suever OP declarou "up" em vez de "pelo menos". No meu entender, isso significa que o suporte> 10k é proibido.
busukxuan

@ Suever Sim, eu acho que posso ser, embora eu não resista a fazê-lo lol. Eu apaguei minha resposta do Sage apenas por causa disso.
busukxuan

6

Mathematica 30 bytes

RealDigits[Pi,10,1,-#][[1,1]]&

f=%

f@0
f@1
f@2
f@3
f@10
f@100
f@599
f@760
f@1000
f@10000

1
4
1
5
8
8
2
4
3
5


5

Sábio, 32 25 bytes

lambda d:`n(pi,9^5)`[d+2]

Minha primeira resposta em um idioma desse tipo.

narredonda pipara 17775 dígitos.


1
Você precisa da printchamada, ou esse é um trecho que só funciona no REPL.
Mego

Isso funciona para (teoricamente) qualquer entrada:lambda d:`n(pi,digits=d+5)`[-4]
Mego

2
@Mego não há execuções "99999"?
Buskxuan

1
@Mego, mas haverá ainda mais "9" execuções. Eu não tenho certeza se a duplicação do comprimento pode torná-lo universal, mas eu não acho que mesmo que pode fazê-lo, devido ao Infinito Macaco Teorema: en.wikipedia.org/wiki/Infinite_monkey_theorem
busukxuan

1
@busukxuan Se você modelar os dígitos não-computados de π como aleatórios, certamente espera que séries arbitrariamente longas de 9s (e não temos motivos para esperar que o real π seja diferente, embora ainda não tenhamos provado isso), mas você só espera um corrida de 9s contanto que sua posição com probabilidade extremamente pequena (embora novamente, não tenhamos provado que o π real não se comporta inesperadamente). Descobrimos séries de pelo menos nove 9s, o que eu acho que é suficiente para quebrar a [-8]proposta.
Anders Kaseorg


4

Mathematica, 23 21 bytes

⌊10^# Pi⌋~Mod~10&

SageMath, 24 bytes

lambda n:int(10^n*pi)%10

@LLlAMnYP Eu tentei isso, mas o Mathematica parece exigir um espaço entre Pie (ou entre #e se a multiplicação for invertida), para que a economia desapareça.
Anders Kaseorg

Na verdade, ele funciona no Mathematica Online (eu estava usando a versão do console), então eu aceito, eu acho.
Anders Kaseorg

4
Estas devem ser respostas separadas. Embora eles usem a mesma estratégia, eles não estão nem perto do mesmo idioma.
Mego

@Mego A política que encontrei não diz que as respostas em diferentes idiomas não podem ser consideradas muito semelhantes. (A resposta que sugere que não foi aceita.) Você está se referindo a outra política ou apenas a uma preferência?
Anders Kaseorg

3

J , 19 15 bytes

10([|<.@o.@^)>:

Toma um inteiro n e emite o n th dígitos de pi. Usa indexação baseada em zero. Para obter o n º dígito, pi computação vezes 10 n +1 , use o piso desse valor e, em seguida, o módulo 10.

Uso

A entrada é um número inteiro estendido.

   f =: 10([|<.@o.@^)>:
   (,.f"0) x: 0 1 2 3 10 100 599 760 1000
   0 1
   1 4
   2 1
   3 5
  10 8
 100 8
 599 2
 760 4
1000 3
   timex 'r =: f 10000x'
1100.73
   r
5

Na minha máquina, leva cerca de 18 minutos para calcular os 10000 th dígitos.

Explicação

10([|<.@o.@^)>:  Input: n
             >:  Increment n
10               The constant n
           ^     Compute 10^(n+1)
        o.@      Multiply by pi
     <.@         Floor it
   [             Get 10
    |            Take the floor modulo 10 and return

3

Clojure, 312 bytes

(fn[n](let[b bigdec d #(.divide(b %)%2(+ n 4)BigDecimal/ROUND_HALF_UP)m #(.multiply(b %)%2)a #(.add(b %)%2)s #(.subtract % %2)](-(int(nth(str(reduce(fn[z k](a z(m(d 1(.pow(b 16)k))(s(s(s(d 4(a 1(m 8 k)))(d 2(a 4(m 8 k))))(d 1(a 5(m 8 k))))(d 1(a 6(m 8 k)))))))(bigdec 0)(map bigdec(range(inc n)))))(+ n 2)))48)))48)))

Então, como você provavelmente pode perceber, não tenho ideia do que estou fazendo. Isso acabou sendo mais cômico do que qualquer coisa. Coloquei "pi em n dígitos" no Google e acabei no página Wikipedia para a fórmula de Bailey – Borwein – Plouffe . Sabendo Cálculo (?) Apenas o suficiente para ler a fórmula, consegui traduzi-lo para o Clojure.

A tradução em si não foi tão difícil. A dificuldade veio de lidar com precisão até n dígitos, pois a fórmula exige (Math/pow 16 precision); que fica enorme muito rápido. Eu precisava usar em BigDecimaltodos os lugares para que isso funcionasse, o que realmente inchava as coisas.

Ungolfed:

(defn nth-pi-digit [n]
  ; Create some aliases to make it more compact
  (let [b bigdec
        d #(.divide (b %) %2 (+ n 4) BigDecimal/ROUND_HALF_UP)
        m #(.multiply (b %) %2)
        a #(.add (b %) %2)
        s #(.subtract % %2)]
    (- ; Convert the character representation to a number...
      (int ; by casting it using `int` and subtracting 48
         (nth ; Grab the nth character, which is the answer
           (str ; Convert the BigDecimal to a string
             (reduce ; Sum using a reduction
               (fn [sum k]
                 (a sum ; The rest is just the formula
                       (m
                         (d 1 (.pow (b 16) k))
                         (s
                           (s
                             (s
                               (d 4 (a 1 (m 8 k)))
                               (d 2 (a 4 (m 8 k))))
                             (d 1 (a 5 (m 8 k))))
                           (d 1 (a 6 (m 8 k)))))))
               (bigdec 0)
               (map bigdec (range (inc n))))) ; Create an list of BigDecimals to act as k
           (+ n 2)))
      48)))

Escusado será dizer que tenho certeza de que há uma maneira mais fácil de fazer isso, se você conhece alguma matemática.

(for [t [0 1 2 3 10 100 599 760 1000 10000]]
  [t (nth-pi-digit t)])

([0 1] [1 4] [2 1] [3 5] [10 8] [100 8] [599 2] [760 4] [1000 3] [10000 5])

Percebi mais tarde que os operadores padrão realmente trabalham com grandes decimais, portanto, os atalhos na parte superior são desnecessários. Eu monto corrigir isso em algum momento. Isso provavelmente derrubará ~ 50 bytes.
Carcigenicate

2

Clojure, 253 bytes

(defmacro q[& a] `(with-precision ~@a))(defn h[n](nth(str(reduce +(map #(let[p(+(* n 2)1)a(q p(/ 1M(.pow 16M %)))b(q p(/ 4M(+(* 8 %)1)))c(q p(/ 2M(+(* 8 %)4)))d(q p(/ 1M(+(* 8 %)5)))e(q p(/ 1M(+(* 8 %)6)))](* a(-(-(- b c)d)e)))(range(+ n 9)))))(+ n 2)))

Calcule o número pi usando esta fórmula . É necessário redefinir a macro with-precision, pois é usada com muita frequência.

Você pode ver a saída aqui: https://ideone.com/AzumC3 1000 e 10000 leva excede o limite de tempo usado em ideone, encolhe os ombros


2

Python 3 , 338 bytes

Essa implementação é baseada no algoritmo de Chudnovsky , um dos algoritmos mais rápidos para estimar pi. Para cada iteração, aproximadamente 14 dígitos são estimados (consulte aqui para mais detalhes).

f=lambda n,k=6,m=1,l=13591409,x=1,i=0:not i and(exec('global d;import decimal as d;d.getcontext().prec=%d'%(n+7))or str(426880*d.Decimal(10005).sqrt()/f(n//14+1,k,m,l,x,1))[n+2])or i<n and d.Decimal(((k**3-16*k)*m//i**3)*(l+545140134))/(x*-262537412640768000)+f(n,k+12,(k**3-16*k)*m

Experimente online!


1

Java 7, 262 260 bytes

import java.math.*;int c(int n){BigInteger p,a=p=BigInteger.TEN.pow(10010).multiply(new BigInteger("2"));for(int i=1;a.compareTo(BigInteger.ZERO)>0;p=p.add(a))a=a.multiply(new BigInteger(i+"")).divide(new BigInteger((2*i+++1)+""));return(p+"").charAt(n+1)-48;}

Utilizado o algoritmo Python 2 do LeakyNun .

Ungolfed & código de teste:

Experimente aqui.

import java.math.*;
class M{
  static int c(int n){
    BigInteger p, a = p = BigInteger.TEN.pow(10010).multiply(new BigInteger("2"));
    for(int i = 1; a.compareTo(BigInteger.ZERO) > 0; p = p.add(a)){
      a = a.multiply(new BigInteger(i+"")).divide(new BigInteger((2 * i++ + 1)+""));
    }
    return (p+"").charAt(n+1) - 48;
  }

  public static void main(String[] a){
    System.out.print(c(0)+", ");
    System.out.print(c(1)+", ");
    System.out.print(c(2)+", ");
    System.out.print(c(3)+", ");
    System.out.print(c(10)+", ");
    System.out.print(c(100)+", ");
    System.out.print(c(599)+", ");
    System.out.print(c(760)+", ");
    System.out.print(c(1000)+", ");
    System.out.print(c(10000));
  }
}

Saída:

1, 4, 1, 5, 8, 8, 2, 4, 3, 5

1

Smalltalk - 270 bytes

Confia na identidade tan⁻¹(x) = x − x³/3 + x⁵/5 − x⁷/7 ..., e isso π = 16⋅tan⁻¹(1/5) − 4⋅tan⁻¹(1/239). O SmallTalk usa aritmética inteira de precisão ilimitada, de modo que funcionará para entradas grandes, se você estiver disposto a esperar!

|l a b c d e f g h p t|l:=stdin nextLine asInteger+1. a:=1/5. b:=1/239. c:=a. d:=b. e:=a. f:=b. g:=3. h:=-1. l timesRepeat:[c:=c*a*a. d:=d*b*b. e:=h*c/g+e. f:=h*d/g+f. g:=g+2. h:=0-h]. p:=4*e-f*4. l timesRepeat:[t:=p floor. p:=(p-t)*10]. Transcript show:t printString;cr

Salve como pi.ste execute como nos seguintes casos de teste. A indexação é baseada.

$ gst -q pi.st <<< 1
1
$ gst -q pi.st <<< 2
4
$ gst -q pi.st <<< 3
1
$ gst -q pi.st <<< 4
5
$ gst -q pi.st <<< 11
8
$ gst -q pi.st <<< 101
8
$ gst -q pi.st <<< 600
2
$ gst -q pi.st <<< 761
4
$ gst -q pi.st <<< 1001
3
$ gst -q pi.st <<< 10001 -- wait a long time!
5

1

JavaScript (Node.js) (Chrome 67+), 75 73 67 63 bytes

n=>`${eval(`for(a=c=100n**++n*20n,d=1n;a*=d;)c+=a/=d+++d`)}`[n]

Experimente online!

Usando π/2=k=0 0k!/(2k+1)!!(mesma lógica usada pela resposta Python de Leaky Nun, mas graças à sintaxe de JS que torna isso mais curto). A entrada é passada para a função como um BigInt. 2 bytes podem ser removidos se a indexação baseada em 1 for usada:

n=>`${eval(`for(a=c=100n**n*20n,d=1n;a*=d;)c+=a/=d+++d`)}`[n]

JavaScript (Node.js) (Chrome 67 ou superior), 90 89 bytes

n=>`${eval(`for(a=100n**++n*2n,b=a-a/3n,c=0n,d=1n;w=a+b;a/=-4n,b/=-9n,d+=2n)c+=w/d`)}`[n]

Experimente online!

Usando π/4=arctan(1/2)+arctan(1/3). A entrada é passada para a função como um BigInt. 2 bytes podem ser removidos se a indexação baseada em 1 for usada:

n=>`${eval(`for(a=100n**n*2n,b=a-a/3n,c=0n,d=1n;w=a+b;a/=-4n,b/=-9n,d+=2n)c+=w/d`)}`[n]

0

Bordo, 24 bytes

 trunc(10^(n+1)*Pi)mod 10

Casos de teste:

> f:=n->trunc(10^(n+1)*Pi)mod 10;
> f(0);
  1
> f(1);
  4
> f(2);
  1
> f(3);
  5
> f(10);
  8
> f(100);
  8
> f(599);
  2
> f(760);
  4
> f(1000);
  3
> f(10000);
  5

0

C #, 252 250 bytes

d=>{int l=(d+=2)*10/3+2,j=0,i=0;long[]x=new long[l],r=new long[l];for(;j<l;)x[j++]=20;long c,n,e,p=0;for(;i<d;++i){for(j=0,c=0;j<l;c=x[j++]/e*n){n=l-j-1;e=n*2+1;r[j]=(x[j]+=c)%e;}p=x[--l]/10;r[l]=x[l++]%10;for(j=0;j<l;)x[j]=r[j++]*10;}return p%10+1;}

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.