Encuentra el enésimo decimal de pi


33

Ya hay 30 desafíos dedicados a pi, pero ninguno te pide que encuentres el enésimo decimal, así que ...

Reto

Para cualquier número entero en el rango de 0 <= n <= 10000visualización, el enésimo decimal de pi.

Reglas

  • Los decimales son cada número después de 3.
  • Su programa puede ser una función o un programa completo
  • Debe generar el resultado en base 10
  • Puede obtener nde cualquier método de entrada adecuado (stdin, input (), parámetros de función, ...), pero no codificado
  • Puede usar la indexación basada en 1 si es nativa de su idioma de elección
  • Usted no tiene que hacer frente a una entrada no válida ( n == -1, n == 'a'o n == 1.5)
  • Se permiten las incorporaciones, si admiten hasta al menos 10k decimales
  • El tiempo de ejecución no importa, ya que se trata del código más corto y no del código más rápido.
  • Este es el , el código más corto en bytes gana

Casos de prueba

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

Como referencia, aquí están los primeros 100k dígitos de pi.


Empotrados? Por ejemplostr(pi())[n+2]
primo

66
Los objetivos de duplicación más cercanos IMO son Calcular potencias de sumas de dígitos truncados de pi (sobrecarga el parámetro, o simplemente sería una diferencia finita aplicada a este desafío), Transmitir pi con precisión (agrega un índice y suprime algo de impresión), y el cifrado de la ventana de Pi .
Peter Taylor

3
@ ¡Por supuesto! Esa regla es solo señalar que 10k es el mínimo que su programa debería ser capaz de manejar
Bassdrop Cumberwubwubwub

44
Sugiero agregar f (599) a los casos de prueba, ya que puede ser fácil equivocarse (necesita unos 3 decimales de precisión adicional).
aditsu

2
También f (760) = 4, que comienza la secuencia 4 999999 8, es fácil de redondear incorrectamente.
Anders Kaseorg

Respuestas:


22

05AB1E, 3 bytes

žs¤

Explicado

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

Pruébalo en línea

Utiliza indexación basada en 1.
Admite hasta 100k dígitos.


Pi a n dígitos no se redondea?
busukxuan

77
@busukxuan No. Utilizó una constante predefinida de pi a 100k dígitos y recupera N de ellos.
Emigna

44
@Emigna Eso es muy útil. Buena solución.
Suever

2
Corto y Sharp, PCG en su mejor momento
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]

La entrada se toma de stdin.


Uso de muestra

$ 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

Tenga cuidado con el uso de n en el algoritmo ... la salida para 599 debe ser 2, no 1. También es posible que desee especificar que está utilizando python 2.
aditsu

@aditsu actualizado. Confirmado para todos n ≤ 1000 .
primo

1
Si considera que nes la entrada más 9, puede evitar los parens.
xnor

@xnor d'oh. Gracias;)
primo

2
Los primeros dígitos generados por este algoritmo son '3.141596535897932 ...' al que le falta un '2' entre los lugares 5 y 6. ¿Por qué? Porque es entonces cuando el operador `` Python 2 '' comienza a agregar una La la cadena.
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

Mejorado por Dennis . ¡Gracias!

El índice está basado en uno.


11

Python 2, 73 71 73 bytes

gracias a @aditsu por aumentar mi puntaje en 2 bytes

Finalmente un algoritmo que puede completar en 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!

Utiliza la fórmula pi = 4*arctan(1)mientras computa arctan(1)usando su serie taylor.


Muy rápido Sin embargo, la indexación 1 no es nativa de Python. Lo último que recuerdo (es cierto que he estado inactivo durante un tiempo), el consenso fue que las funciones deben definirse, por ejemplo f=lambda n:....
primo

2
Casi todas las lambda aquí son anónimas (puedes buscar respuestas en Python en este sitio)
Leaky Nun

Meta publicación relevante . Parece estar en violación de la Regla 1 y 3 (después de ejecutar el código, no hay manera de capturar una referencia de función; tendría que ser escrito a máquina por cada entrada (la definición de función (lambda n:`p`[n+1])(1), (lambda n:`p`[n+1])(2), ...).
Primo

1
No puede ejecutar el código directamente. Es similar a colocar importdeclaraciones de antemano, solo que esto hace algunas variables globales de antemano.
Leaky Nun

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

7

MATL, 11 10 bytes

1 byte guardado gracias a @Luis

YPiEY$GH+)

Esta solución utiliza indexación basada en 1

Pruébalo en línea

Todos los casos de prueba

Explicación

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, sí, supongo que la salida ya es una cadena. Doh!
Suever

@LuisMendo Oh, en realidad nunca pensé en eso. Siempre uso YPen mis pruebas de la caja de herramientas simbólicas
Suever

¿Está YP realmente permitido? La pregunta dice que está permitido si admite <= 10k dígitos
busukxuan

@Suever OP declaró "hasta" en lugar de "al menos". A mi entender, eso significa que> 10k está prohibido.
busukxuan

@Suever Sí, creo que sí, aunque no puedo resistirme a hacerlo jajaja. Eliminé mi respuesta de Sage solo por eso.
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

Salvia, 32 25 bytes

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

Mi primera respuesta en un lenguaje de este tipo.

nse redondea pia 17775 dígitos.


1
Necesita la printllamada, o de lo contrario, este es un fragmento que solo funciona en REPL.
Mego

Esto funciona para (en teoría) cualquier entrada:lambda d:`n(pi,digits=d+5)`[-4]
Mego

2
@Mego no hay carreras "99999"?
busukxuan

1
@Mego pero luego habrá incluso más "9" carreras. No estoy seguro de si duplicar la longitud puede hacerlo universal, pero creo que ni siquiera eso puede hacerlo, debido al Teorema del mono infinito: en.wikipedia.org/wiki/Infinite_monkey_theorem
busukxuan

1
@busukxuan Si modela los dígitos no calculados de π como aleatorios, ciertamente espera series arbitrariamente largas de 9s (y no tenemos ninguna razón para esperar que el π real sea diferente, aunque no lo hemos probado), pero solo espera un corrida de 9s siempre que su posición con una probabilidad muy pequeña (aunque, una vez más, no hemos demostrado que el π real no se comporte inesperadamente). Hemos encontrado tiradas de al menos nueve 9, lo que creo que es suficiente para romper la [-8]propuesta.
Anders Kaseorg


4

Mathematica, 23 21 bytes

⌊10^# Pi⌋~Mod~10&

SageMath, 24 bytes

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

@LLlAMnYP Lo intenté, pero Mathematica parece requerir un espacio entre Piy (o entre #y si se invierte la multiplicación), por lo que el guardado desaparece.
Anders Kaseorg

En realidad funciona en Mathematica Online (había estado usando la versión de consola), así que supongo que lo tomaré.
Anders Kaseorg

44
Estas deberían ser respuestas separadas. Aunque usan la misma estrategia, no están cerca del mismo idioma.
Mego

@Mego La política que encontré no dice que las respuestas en diferentes idiomas no pueden considerarse muy similares. (La respuesta sugiere que no fue aceptada). ¿Se refiere a otra política o simplemente a una preferencia?
Anders Kaseorg

3

J , 19 15 bytes

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

Toma un número entero n y emite el n º dígitos de pi. Utiliza indexación basada en cero. Para obtener el n º dígitos, pi por compute 10 n 1 , la palabra de ese valor, y luego la lleva modulo 10.

Uso

La entrada es un entero extendido.

   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

En mi máquina, se tarda unos 18 minutos para calcular el 10.000 º dígitos.

Explicación

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

Entonces, como probablemente pueda ver, no tengo idea de lo que estoy haciendo. Esto terminó siendo más cómico que nada. Busqué en Google "pi to n digits" y terminé en la página de Wikipedia para la fórmula Bailey – Borwein – Plouffe . Sabiendo apenas apenas el cálculo (?) Para leer la fórmula, logré traducirlo a Clojure.

La traducción en sí no fue tan difícil. La dificultad vino de manejar precisión hasta n dígitos, ya que la fórmula lo requiere (Math/pow 16 precision); que se vuelve enorme muy rápido. Necesitaba usar en BigDecimaltodas partes para que esto funcionara, lo que realmente hinchaba las cosas.

Sin golf:

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

No hace falta decir que estoy seguro de que hay una manera más fácil de hacerlo si sabes algo de matemáticas.

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

Más tarde me di cuenta de que los operadores estándar realmente funcionan con grandes decimales, por lo que los atajos en la parte superior son innecesarios. Monto arreglar esto en algún momento. Eso probablemente eliminará ~ 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 el número pi usando esta fórmula . Tiene que redefinir la macro with-precisionya que se usa con demasiada frecuencia.

Puede ver la salida aquí: https://ideone.com/AzumC3 1000 y 10000 toma excede el límite de tiempo utilizado en ideone, encoge de hombros


2

Python 3 , 338 bytes

Esta implementación se basa en el algoritmo Chudnovsky , uno de los algoritmos más rápidos para estimar pi. Para cada iteración, se estiman aproximadamente 14 dígitos (consulte aquí para obtener más detalles).

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

Pruébalo en línea!


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

Utiliza el algoritmo Python 2 de @ LeakyNun .

Ungolfed y código de prueba:

Pruébalo aquí.

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

Salida:

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

1

Smalltalk - 270 bytes

Se basa en la identidad tan⁻¹(x) = x − x³/3 + x⁵/5 − x⁷/7 ..., y eso π = 16⋅tan⁻¹(1/5) − 4⋅tan⁻¹(1/239). SmallTalk utiliza aritmética de enteros de precisión ilimitada, por lo que funcionará para entradas grandes, si está dispuesto 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

Guardar como pi.sty ejecutar como en los siguientes casos de prueba. La indexación está basada en uno.

$ 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]

Pruébalo en línea!

Utilizando π/ /2=k=0 0k!/ /(2k+1)!!(La misma lógica utilizada por la respuesta Python de Leaky Nun, pero gracias a la sintaxis de JS que hace esto más corto). La entrada se pasa a la función como un BigInt. Se pueden eliminar 2 bytes si se utiliza la indexación basada en 1:

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

JavaScript (Node.js) (Chrome 67+), 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]

Pruébalo en línea!

Utilizando π/ /4 4=arctan(1/ /2)+arctan(1/ /3). La entrada se pasa a la función como un BigInt. Se pueden eliminar 2 bytes si se utiliza la indexación basada en 1:

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

Arce, 24 bytes

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

Casos de prueba:

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

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.