Aproximar el número de plástico


24

El reto

El número plástico es un número relacionado con la proporción áurea, con muchas propiedades matemáticas interesantes. Como tal, hay muchos enfoques que se pueden usar para calcular el número.

Para especificar con precisión el número para los propósitos de este desafío, usaremos la siguiente definición (aunque hay muchas definiciones equivalentes, y puede usar cualquier definición que desee siempre que se trate del mismo número):

El número plástico es un número real ρ tal que ρ ³ = ρ +1.

Su desafío es escribir un programa o función que tome un entero x como entrada (con x > 1), y produzca una aproximación a ρ como salida, de modo que cuanto mayor sea el valor de x , más se acerca la salida a ρ ( con a lo sumo muchas excepciones; permanecer en el mismo valor cuenta como "más cercano" para este propósito), y para cualquier número positivo δ , hay alguna entrada x en su programa que produce una salida que está dentro de δ de ρ .

Aclaraciones

  • Si está emitiendo a través de un método que inherentemente genera cadenas (por ejemplo, la secuencia de salida estándar), puede formatear la salida en decimal (por ejemplo 1.3247179572) o como una relación de dos enteros con un /carácter entre ellos.
  • Si está generando un valor dentro de su lenguaje de programación (por ejemplo, regresando de una función), debe ser de tipo fijo, punto flotante o racional. (En particular, no puede usar tipos de datos que almacenen números simbólicamente, a menos que se usen solo para mantener la relación de dos enteros. Por lo tanto, si está usando Mathematica o un lenguaje similar, deberá incluir el extra código para generar realmente los dígitos de la salida).
  • Su respuesta debe funcionar en una variante hipotética de su idioma en la que los enteros pueden ser arbitrariamente grandes, y la memoria (incluida la pila) es ilimitada. Es posible que no asuma que aritmética de punto flotante en su idioma es arbitraria precisa, sino que debe utilizar su exactitud real (lo que significa que la salida de un número de coma flotante sólo va a ser posible en los idiomas en que la exactitud de los números de coma flotante puede ser controlado en tiempo de ejecución).
  • x puede tener el significado que desee (siempre que al aumentarlo se obtengan resultados más precisos). Me imagino que la mayoría de las presentaciones harán que controle el número de dígitos de salida para producir, o el número de iteraciones del algoritmo utilizado por su programa para converger en el número plástico, pero otros significados son aceptables.

Caso de prueba

Aquí están los primeros dígitos del número plástico:

1.32471795724474602596090885

Hay más dígitos disponibles en OEIS .

Condición de victoria

Como es habitual para el , más corto es mejor, medido en bytes. Sin embargo, siéntase libre de publicar respuestas incluso si no ganan, siempre que agreguen algo (por ejemplo, un idioma diferente o un algoritmo diferente) a las respuestas existentes.


1
hmm, (cbrt (108 + 12 * sqrt (69)) + cbrt (108-12 * sqrt (69))) / 6 este parece ser un buen momento para usar 'la aproximación de Drake': sqrt (69) = 8. algo bit.ly/2rCqedX ^ _ ^
DrQuarius

2
¿Podemos suponer también que la profundidad de recursión / pila es ilimitada?
xnor

Para aclarar el segundo punto, ¿podemos usar bibliotecas de precisión arbitraria (por ejemplo, mpmath en Python)? Usan un tipo de datos auxiliar, pero ¿lo considera como almacenamiento de cosas "simbólicamente"?
Batman

1
Bueno, al menos esperaría que las respuestas converjan a ρ . Además, una solución "honesta" podría fallar fácilmente la prueba x> y -> | ρx - ρ | > | ρy - ρ | para un número finito de (x, y) pares. Si eso no es aceptable, creo que esto debería hacerse más explícito en la especificación.
Dennis

66
Muchos respondedores han caído en la trampa (?) De calcular una aproximación de x dígitos a ρ, el problema es que probablemente haya infinitamente muchas x, de modo que una aproximación de dígitos (x + 1) no sea mejor que una aproximación de x dígitos. Probablemente debería aclarar si pretendía que esto se permitiera. Si no lo hace, reemplace "más cerca" por "estrictamente más cerca"; si lo hace, "al menos tan cerca", o algo así. También podría considerar el requisito más flexible de que la secuencia converja a ρ, lo que además permitiría la respuesta de xnor.
Anders Kaseorg

Respuestas:


10

Python 2 , 49 bytes

n=x=input()
while n**3/x/x<n+x:n+=1
print n,'/',x

Pruébalo en línea!

La idea es expresar el ρcon ρ³=ρ+1como una fracción n/xcuyo denominador xes el parámetro de precisión de entrada. Tomamos (n/x)³=n/x+1y despejamos denominadores para obtener n³=x²(x+n).

Como el LHS aumenta nmás rápido que el RHS, podemos aproximar el punto de igualdad ncomo el más pequeño con n³≥x²(x+n). El código cuenta nhasta que este sea el caso, comenzando en el xcual es más pequeño.

Un pequeño byte guardado es dividir ambos lados entre escribir n³/x²≥x+n(negado en la whilecondición). Esta es la división de piso en el código, pero la parte fraccional perdida es insignificante.

Una alternativa de la misma longitud en su lugar pone xcomo numerador:

Python 2 , 49 bytes

n=x=input()
while x**3/n/n<n+x:n-=1
print x,'/',n

Pruébalo en línea!


Aunque esta salida converge a ρ (∀ε> 0 ∃x₀ ∀x ≥ x₀ | f (x) - ρ | <ε), no satisface “cuanto mayor es el valor de x, más se acerca la salida a ρ (con a lo sumo muchas excepciones) ”(∃x₀ ∀x ≥ x₀ | f (x + 1) - ρ | <| f (x) - ρ |).
Anders Kaseorg

Este problema se puede solucionar mediante el uso en 2**input()lugar de simplemente input(); entonces, cada aproximación será tan precisa como la anterior.

10

Mathematica, 20 bytes

#^3-#-1&~Root~1~N~#&

La Rootfunción incorporada de Mathematica da las soluciones a una ecuación polinómica f[x] == 0.

Explicación

#^3-#-1&~Root~1~N~#&
                   &  (* Function *)
#^3-#-1&              (* A pure-function polynomial, x^3-x-1 *)
        ~Root~1       (* Find the first root *)
               ~N~#   (* approximate to (input) digits *)

Muestra de E / S

In[1]:= f=#^3-#-1&~Root~1~N~#&;
        f[1]

Out[1]= 1.

In[2]:= f[9]

Out[2]= 1.32471796

In[3]:= f[100]

Out[3]= 1.324717957244746025960908854478097340734404056901733364534015050302827851245547594054699347981787280

PD: Root[x^3-x-1,1]~N~#&funciona bien (a pesar de no decir que xes una variable) para el mismo recuento de bytes.
Greg Martin

@AndersKaseorg: Cambié esa regla porque estaba claramente quebrada. No se invalidaron las respuestas válidas, pero algunas respuestas (como esta) se volvieron válidas.

6

Mathematica, 27 bytes

x/.Solve[x^3==x+1>2,x]~N~#&

-1 byte de Martin
-2 bytes de ovs

entrada

[27]

salida

{1.32471795724474602596090885}


Solve[x^3==x+1>2,x]~N~#&para 24 bytes
ovs

1
El resultado de esto es {{x -> 1.32...}}sin embargo. Es posible que desee verificar con ais si ese es un formato de salida válido.
Martin Ender

ok .. todo arreglado, supongo
J42161217

Todavía es en {1.32...}realidad, pero ese formato es probablemente menos polémico.
Martin Ender

1
Hice el desafío un poco más general para que esto fuera válido, no estaba destinado a rechazar las soluciones de "primeros x dígitos". Entonces esto es válido ahora, aunque no lo era antes.

6

sed , 67 60 (59 + 1) bytes

s,^,1/1/1 ,
:;s,(1*/(1*)/(1*).*)1$,\2\3/\1,
t
s,(/1*).*,\1,

Pruébalo en línea!

+1 para la -Ebandera (ERE en lugar de BRE). La entrada y la salida son ambas unarias: la entrada 11111 para x = 5, por ejemplo, la salida es una fracción de dos números unarios: la entrada 11111 mencionada anteriormente produce la salida 11111/1111 (5/4 en decimal).

Aproxima el número plástico como una fracción entre elementos consecutivos de la secuencia de Padovan .


1
FWIW no necesita un espacio después del bcomando, pero puede acortarlo aún más utilizando la etiqueta vacía ( :y bsin argumento). tio.run/#%23K05N@f@/…
Jordania

Oh excelente Y puedo guardar otros 4 bytes usando en tlugar de b, así que es un buen guardado. Gracias :)
FireFly

5

Mathematica, 27 bytes

Nest[(1+#)^(1/3)&,1,#]~N~#&

Utiliza una aproximación truncada de la forma radical cúbica anidada ³√ (1 + ³√ (1 + ³√ (1 + ...))) . Si bien la salida siempre tendrá decimales x-1 , el resultado es en realidad menos preciso que eso, porque la expresión converge más lentamente que un dígito por iteración ( x también se usa como el número de radicales anidados que se calculan). Por ejemplo x = 100 da

_________________________________________________________________________
1.324717957244746025960908854478097340734404056901733364534015050302827850993693624204577670741656151

donde la parte sobrepuesta es correcta.


Estaba planeando escribir este algoritmo dc, pero me bloqueé porque resulta que no tiene una operación de raíz cúbica, y elevar un número a la potencia ⅓ tampoco funciona :-( Al menos siempre puedes contar con Mathematica tendrá construcciones apropiadas ...

3
@ ais523 En realidad, CubeRootpero nadie tiene bytes para eso.
Martin Ender

4

Octava , 50 bytes

@(n)char(digits(n)*0+vpasolve(sym('r^3-r-1'))(1));

Pruébalo en línea!

Define una función anónima, con nel número deseado de dígitos de salida.

Esta respuesta abusa de que digitsdevuelve la configuración actual para el número de dígitos en aritmética de precisión variable. Esto significa que podemos usarlo en una función anónima sin errores sobre 'Demasiados argumentos de salida'.

Aparte de eso, es realmente sencillo: vpasolvees la abreviatura de resolución aritmética de precisión variable, con la precisión establecida por la última llamada de digits. Dado que vpaes un tipo de datos simbólico en Octave, que está prohibido según la especificación, simplemente envolvemos toda la función char(...)para obtener una salida de cadena. Tenga en cuenta que en solvey vpasolve, el f==0está implícito, por lo que r^3==r+1ha sido reemplazado porr^3-r-1 (==0)


Fui y cambié la pregunta para que no rechace respuestas como esta (no estaba destinado a hacerlo).

@ ais523 ¡Gracias por la notificación!
Sanchises

4

MATL ( 27 28 bytes)

7BG:"t@)y@Q)+h]tG3+)yG2+)/

Mi primera solución (27 bytes)

Pruébalo en línea!

Ciertamente no es óptimo, todavía me estoy acostumbrando a MATL.

Explicación:

Creo una secuencia de Padovan hasta la entrada + 3 y luego encuentro la relación de los dos últimos números.

7B     % Turn 7 into binary to give 1 1 1 
G:"    % For k=1:input do...
t@)    % Existing sequence member k
y@1+)  % Existing sequence member k+1
+h     % Add them together and concatenate to the sequence array
]      % End loop
tG3+)  % Final sequence member
yG2+)  % Second last sequence member
/      % Divide to approximate ρ

Salida de fracción adecuada (35 bytes) (28 bytes, @Sanchises):

Sin embargo, la primera solución no satisface la necesidad de precisión arbitraria siendo el límite de coma flotante de la configuración MATL predeterminada. Entonces, en lugar de agregar varios bytes para extender esta precisión, es más simple tomar la ruta de fracción adecuada y escribir una fracción de los dos enteros finales en los elementos (N-1) th y N th de la secuencia de Padovan truncada.

por ejemplo, "114/86"

7BG: "t @) y @ 1 +) + h] tG3 +) V '/' YcyG2 +) VYc

7BG:"t@tQh)sh]tJ)V47hyJq)Vh&

Cortesía del usuario @Sanchises. :)

Pruébalo en línea!

Evaluación no iterativa:

Notablemente, mi código más corto para la versión 'exacta' es (23 bytes):

1-1h69X^12**108+1I/^6/s

Pruébalo en línea!

... pero no da precisión arbitraria. Me pregunto si alguien puede ajustar esto para cumplir con las reglas (usar la entrada, etc.) y aun así agregar menos de 5 bytes. :PAGS


1
1+puede acortarse a Q.Con eso en mente, puede reemplazar @)y@1+)+con solo @tQh)s. Además, puede usar Jpara indicar el final de una matriz; y finalmente, MATL no distingue entre matrices normales y matrices de caracteres, por lo que puede reemplazar Ycpor h(no necesita la funcionalidad adicional de Yc). Esto proporciona solo 28 bytes: 7BG:"t@tQh)sh]tJ)V47hyJq)Vh&(observe el &para evitar la salida superflua y el reemplazo '/'por 47).
Sanchises

1
Felicitaciones por 7Blllv
eso

1
@DrQuarius La última versión siempre se puede encontrar en este enlace de GitHub
Luis Mendo

1
@DrQuarius No, este comportamiento está presente en la especificación MATL bastante antigua que generalmente uso. Realmente debería consultar la Tabla 3. No solo el portapapeles Jcontiene de forma predeterminada 1j, sino que el portapapeles Ltambién contiene muchas funciones útiles de indexación (tenga en cuenta que 1jes igual enden MATL).
Sanchises

1
Además, no te preocupes, soy ingeniero mecánico. Creo que MATL (AB) tiene poco uso fuera de un entorno científico, por lo que supongo que la mayoría de los golfistas de MATL (AB) / Octave son de fuera de CS.
Sanchises

4

M , 15 14 bytes

²×3’
*3Ḥ‘÷Ç
Ç¡

Pruébalo en línea!

Algoritmo

Esto usa racionales y el método de Newton. Específicamente, para la entrada x , se aplican las primeras iteraciones x con el valor inicial x .

Estamos tratando de encontrar una raíz específica del polinomio p (t) = t³ - t - 1 . El método de Newton logra esto tomando un valor inicial t 0 - suficientemente cerca de ρ - y definiendo recursivamente una secuencia por
t n + 1 = t n - p (t n ) / p '(t n ) .

Como p '(t) = 3t² -1 , obtenemos
t n + 1 = t n - (t n ³ - t n - 1) / (3t n ² - 1) = (3t n ³ - t n - t n ³ + t n + 1) / (3t n ² - 1) = (2t n ³ + 1) / (3t n ² - 1) .

Tenga en cuenta que la aproximación inicial x empeora progresivamente a medida que x aumenta. Si bien la salida para x = 3 es ligeramente menos precisa que la salida para x = 2 , dado que el método de Newton converge cuadráticamente a ρ , esto no debería ser un problema para valores grandes de x .

Cómo funciona

Ç¡    Main link. Argument: x

Ç¡    Call the second helper link x times, which initial argument x.


*3Ḥ‘÷Ç  Second helper link. Argument: t

*3      Compute t³.
  Ḥ     Unhalve; yield 2t³.
   ‘    Increment; yield 2t³+1.
     Ç  Call the first helper link with argument t.
    ÷   Divide the left result by the right one.


²×3’    First helper link. Argument: t

²       Compute t².
 ×3     Compute 3t².
   ’    Decrement; yield 3t²-1.

Lástima que no puedas usar ... µ¡...
Erik the Outgolfer



1

Carbón , 28 bytes

AIθθAθνW‹∕∕Xν³θθ⁺νθA⁺ν¹νI∕νθ

Pruébalo en línea! Enlace al modo detallado. También aparentemente me equivoqué Dividey IntDivide: |
Utiliza el mismo método que las respuestas de Python y JavaScript.


1

NewStack , 14 bytes

¹Fᵢ{E2x³⁺÷3x²⁻

Descompostura:

¹                Add arbitrary number 1 to the stack.
 Fᵢ{             Define for loop with a user's input amount of itterations.
    E            Define new edit for element 0 (element 0 being the 1 added. earlier).
     2x³⁺÷3x²⁻   update x to equal (2x^3+1)/(3x^2-1). (x = element 0).

Cómo funciona:

La fórmula (2x 3 +1) / (3x 2 -1) proviene de la simplificación del método de Newton para la ecuación x 3 = x + 1. Lo puedes encontrar aquí . Repitiendo este proceso una infinidad de veces converge al número plástico. Su tasa de convergencia es bastante rápida, alrededor de 2.6 decimales por iteración.

INPUT ITERATION >> VALUE
0 >> 1
1 >> 1.5
2 >> 1.3478260869565217
3 >> 1.325200398950907
4 >> 1.3247181739990537
5 >> 1.3247179572447898
6 >> 1.324717957244746    <- 16 decimal precision in 6 iterations!
...
100 >> 1.324717957244746

Alternativa de secuencia de Padua, 27 25 17 bytes

¹Fᵢ{[ƨ2+ƨ3]ℲƤƨ/ƨ2

Descompostura:

¹                  Append first element of Padovan sequence.
 Fᵢ{       Ⅎ       Define for loop of user's input amount of iterations.
    [ƨ2+ƨ3]        Append sum second and third to last elements.
            Ƥƨ/ƨ2  Print ratio of last two elements.

-2 bytes eligiendo una mejor estrategia de impresión

-8 bytes eligiendo la mejor manera de indexar la pila

Cómo funciona:

A medida que continúa la secuencia de Padovan , la relación de los dos últimos elementos converge al número plástico.

INPUT ITERATION >> VALUE
0 >> 1
1 >> 2
...
10 >> 1.3157894736842106
...
89 >> 1.324717957244746    <- 16 decimal precision in 89 iterations
...
100> > 1.324717957244746

0

Clojure, 46 bytes

#(nth(iterate(fn[i](Math/pow(inc i)(/ 3)))1)%)

Utiliza la fórmula iterada de la raíz cúbica. Esto es un poco más interesante pero más largo:

(def f #(apply comp(repeat %(fn[i](Math/pow(inc i)(/ 3))))))

((f 10)1)
1.3247179361449652

“Es posible que no asuma que aritmética de punto flotante en su idioma es arbitraria precisa, sino que debe utilizar su exactitud real (lo que significa que la salida de un número de coma flotante sólo va a ser posible en los idiomas en que la exactitud de los números de punto flotante puede ser controlado en tiempo de ejecución). ”
Anders Kaseorg

Ooh, no me di cuenta de eso, qué fastidio. E implementar raíz cúbica con BigDecimal parece bastante complicado.
NikoNyrh

0

Javascript, 36 bytes

f=(x,n=x)=>n**3/x/x<n+x?f(x,++n):n/x

Funciona igual que la respuesta superior de Python. No console.logse incluyó porque si ejecuta f(x)en la consola, se registrará automáticamente.

f=(x,n=x)=>n**3/x/x<n+x?f(x,++n):n/x
console.log(f(300))


0

> <> , 38 + 3 = 41 bytes

11\n;
?!\}2,:01{::::}**-+0(?$-{+{1-:}

Espera que la entrada esté presente en la pila al inicio del programa, por lo que +3 bytes para el -vindicador.

Pruébalo en línea!

Efectivamente realiza una búsqueda binaria para reducir el valor de salida. Aumentar xaumenta el número de iteraciones a realizar.

Editar: cálculo refactorizado ligeramente para guardar 1 byte, versión anterior:

11\n;
?!\}2,:0{::::}**$-1-0)?$-{+{1-:}


0

TI-BASIC, 21 bytes

:Prompt X //Prompt for input, 3 bytes
:While X  //While X, 3 bytes
:³√(1+Y→Y //Calculate cube root of 1+Y and store to Y, 7 bytes
:DS<(X,0  //Decrement X and skip next command (which doesn't do anything), 5 bytes
:End      //End While loop, 2 bytes
:Y        //Display Y, 1 byte

Utiliza esta fórmula recursiva .

Curiosamente, codificar el número y redondearlo da el mismo número de bytes:

TI-BASIC, 21 bytes

:Prompt X    //Prompt for input, 3 bytes
:.5√(3       //Store √(3)/2 to Ans, 5 bytes
:Ansֿ¹cosh(3ֿ¹coshֿ¹(3Ans //Store the plastic number to Ans, 9 bytes
:round(Ans,X //Round the plastic number X decimal digits, 4 bytes

Utiliza esta fórmula trigonométrica .


No creo que pueda usar las carrozas de TI-BASIC aquí:Your answer must work in a hypothetical variant of your language in which integers can be arbitrarily large, and memory (including stack) is unlimited. You may not assume that floating-point arithmetic in your language is arbitrarily accurate, but must instead use its actual accuracy (meaning that outputting a floating-point number is only going to be possible in languages where the accuracy of floating-point numbers can be controlled at runtime).
lirtosiast

0

C # , 317 bytes

using m=System.Math;a=x=>{if(a==0)return "1/1";var d=a(x-1).Split('/');var b=int.Parse(d[0]);var c=int.Parse(d[1]);return string.Format("{0}/{1}",(2*m.Pow(b,3)+m.Pow(c,3)).ToString(new string('#',int.MaxValue.ToString().Length)),(3*m.Pow(b,2)*c-m.Pow(c,3)).ToString(new string('#',int.MaxValue.ToString().Length)));};

Devuelve el resultado como una fracción.

Explicación

Utiliza el método de Newton con iteraciones x para encontrar la raíz del polinomio p ^ 3-p-1 = 0. La fórmula es x_n = 1- (f (x_ (n-1))) / (f '(x_ (n-1))), y x_0 es un punto de partida.

La derivada de polinomios es 3p ^ 2-1, y digamos x_ (n-1) = b / c. Luego, usando la fórmula anterior, obtenemos que x_n = (2 b ^ 3 + c ^ 3) / (3 b ^ 2 cc ^ 3). Digamos también que comenzamos desde 1, esto sucederá cuando x = 2, porque x> 1, y es un número entero. Código ideado y comentado:

using System;
string PlasticNumber(int x)
{
    if (x == 2) 
        return "1/1";                 

//If x=2, we return our starting value, but we need to return it as a fraction

    var d = PlasticNumber(x - 1).Split('/');
    var b = System.Convert.ToInt32(d[0]);
    var c = int.Parse(d[1]);

//We parse the previous value of the fraction, and put it into two variables

    return string.Format("{0}/{1}", 
        (2 * Math.Pow(b, 3) + Math.Pow(c, 3))
        .ToString(new string('#', int.MaxValue.ToString().Length)),
        (3 * Math.Pow(b, 2) * c - Math.Pow(c, 3))
        .ToString(new string('#', int.MaxValue.ToString().Length)));

//We return the result as a fraction, but it's important not to return it in
  scientific notation, because that will cause issues in the parsing process 

}


0

Axioma, 96 bytes

h(n:NNI):Float==(n>1.E5=>-1;n:=n+1;j:=digits(n::PI);r:=solve(x^3-x=1,10.^-n);digits(j);rhs(r.1))

resultados

(31) -> [h(i) for i in 0..10]
   (31)
   [1.0, 1.3, 1.33, 1.325, 1.3247, 1.32472, 1.324718, 1.324718, 1.32471796,
    1.324717957, 1.3247179572]
                                                         Type: List Float

cómo puede ver h (2) debe ser 1.32 y no 1.33, por lo que hay algún error en los últimos dígitos

Entonces habría uno de 110 bytes

g(n:NNI):Float==(n>1.E5=>-1;n:=n+1;j:=digits(n::PI);x:=sqrt(23./108);r:=(.5+x)^(1/3)+(.5-x)^(1/3);digits(j);r)

Utiliza la fórmula para resolver la ecuación de grado III de tipo x ^ 3-3 * p * x-2 * q = 0 en el caso q ^ 2-p ^ 3> = 0 que es m = sqrt (q ^ 2- p ^ 3) yx = (q + m) ^ (1/3) + (qm) ^ (1/3)

En nuestro caso, r ^ 3-r-1 = 0, esto puede escribirse como r ^ 3-3 * (1/3) r-2 * (1/2) = 0, entonces p = 1/3 q = 1/2 m = 1 / 4-1 / 27 = 23/108 x = (0.5 + m) ^ (1/3) + (0.5-m) ^ (1/3)

este que usa la iteración de Newton con el punto de inicio r = 1

f(n:NNI):Float==(n>1.E5=>-1;n:=n+1;j:=digits(n::PI);e:=10^-n;r:=1.;repeat(v:=(r^3-r-1)/(3*r^2-1);abs(v)<e=>break;r:=r-v);digits(j);r)

cambia en la función, valor de dígitos para obtener un obj de n + 1 dígitos después del punto flotante. Al final, el valor de los dígitos () se asigna nuevamente al valor de referencia.


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.