Aproximado do número do plástico


24

O desafio

O número do plástico é um número relacionado à proporção áurea, com muitas propriedades matemáticas interessantes. Como tal, existem muitas abordagens que podem ser usadas para calcular o número.

Para especificar com precisão o número para os objetivos deste desafio, usaremos a seguinte definição (embora existam muitas definições equivalentes e você possa usar qualquer definição que desejar, desde que chegue ao mesmo número):

O número do plástico é um número real ρ tal que ρ ³ = ρ +1.

Seu desafio é escrever um programa ou função que use um número inteiro x como entrada (com x > 1) e produza uma aproximação de ρ como saída, de modo que, quanto maior o valor de x , maior a proximidade de ρ ( com no máximo muitas exceções finitas; permanecer no mesmo valor conta como "mais próximo" para essa finalidade) e para qualquer número positivo δ , há alguma entrada x no seu programa que produz uma saída dentro de δ de ρ .

Esclarecimentos

  • Se você estiver produzindo através de um método que gera inerentemente seqüências de caracteres (por exemplo, o fluxo de saída padrão), você pode formatar a saída em decimal (por exemplo 1.3247179572) ou como uma proporção de dois números inteiros com um /caractere entre eles.
  • Se você estiver produzindo como um valor na sua linguagem de programação (por exemplo, retornando de uma função), ela deve ser do tipo ponto fixo, ponto flutuante ou racional. (Em particular, você não pode usar tipos de dados que armazenam números simbolicamente, a menos que sejam usados ​​apenas para manter a proporção de dois números inteiros. Portanto, se você estiver usando o Mathematica ou um idioma semelhante, precisará incluir o extra código para realmente gerar os dígitos da saída.)
  • Sua resposta deve funcionar em uma variante hipotética do seu idioma, na qual os números inteiros podem ser arbitrariamente grandes e a memória (incluindo a pilha) é ilimitada. Você não pode presumir que a aritmética de ponto flutuante no seu idioma seja arbitrariamente precisa, mas deve usar sua precisão real (o que significa que a saída de um número de ponto flutuante só será possível em idiomas onde a precisão dos números de ponto flutuante pode ser controlado em tempo de execução).
  • x pode ter o significado que você quiser (desde que aumentado, produza resultados mais precisos). Eu imagino que a maioria das submissões controlará o número de dígitos da saída a ser produzida ou o número de iterações do algoritmo usado pelo seu programa para convergir para o número plástico, mas outros significados são aceitáveis.

Caso de teste

Aqui estão os primeiros dígitos do número do plástico:

1.32471795724474602596090885

Mais dígitos estão disponíveis no OEIS .

Condição de vitória

Como de costume no , quanto menor, melhor, medido em bytes. No entanto, sinta-se à vontade para postar respostas, mesmo que não ganhem, desde que adicionem algo (por exemplo, um idioma diferente ou um algoritmo diferente) às respostas existentes.


11
hmm, (cbrt (108 + 12 * sqrt (69)) + cbrt (108-12 * sqrt (69))) / 6 este parece ser um bom momento para usar `a aproximação de Drake ': sqrt (69) = 8. algo bit.ly/2rCqedX ^ _ ^
DrQuarius

2
Também podemos assumir que a profundidade da recursão / pilha é ilimitada?
xnor

Para esclarecer o segundo ponto, podemos usar bibliotecas de precisão arbitrárias (por exemplo, mpmath em Python)? Eles usam um tipo de dados auxiliar, mas você considera isso como armazenamento "simbólico"?
Batman

11
Bem, pelo menos eu esperaria que as respostas convergissem para ρ . Além disso, uma solução "honesta" poderia facilmente falhar no teste x> y -> | ρx - ρ | > | ρy - ρ | para um número finito de (x, y) pares. Se isso não for aceitável, acho que isso deve ser mais explícito nas especificações.
Dennis

6
Muitos respondentes caíram na armadilha (?) De calcular uma aproximação de dígito x para ρ, o problema é que provavelmente existem infinitamente muitos x tais que uma aproximação de dígitos (x + 1) não é melhor do que uma aproximação de dígitos x. Provavelmente, você deve esclarecer se pretende que isso seja permitido. Caso contrário, substitua "mais perto" por "estritamente mais próximo"; se você fizer, "pelo menos o mais próximo", ou algo assim. Você também pode considerar o requisito mais flexível de que a sequência converja para ρ, o que permitiria adicionalmente a resposta do xnor.
Anders Kaseorg

Respostas:


10

Python 2 , 49 bytes

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

Experimente online!

A idéia é expressar o ρcom ρ³=ρ+1como uma fração n/xcujo denominador xé o parâmetro de precisão da entrada. Tomamos (n/x)³=n/x+1e limpamos denominadores para obter n³=x²(x+n).

Como o LHS aumenta nmais rapidamente que o RHS, podemos aproximar o ponto de igualdade ncomo o menor com n³≥x²(x+n). O código conta naté que este seja o caso, começando pelo xqual é menor.

Uma pequena economia de bytes é dividir os dois lados por escrever n³/x²≥x+n(negado na whilecondição). Esta é a divisão de piso no código, mas a parte fracionária perdida é insignificante.

Uma alternativa de mesmo comprimento coloca xcomo numerador:

Python 2 , 49 bytes

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

Experimente online!


Embora essa saída converja para ρ (>ε> 0 ∃x₀ ∀x ≥ x₀ | f (x) - ρ | <ε), ela não satisfaz “quanto maior o valor de x, mais próxima a saída fica de ρ (com no máximo muitas exceções finitas) ”(∃x₀ ∀x ≥ x₀ | f (x + 1) - ρ | <| f (x) - ρ |).
Anders Kaseorg 16/06

Esse problema pode ser corrigido usando, 2**input()e não apenas input(); então, cada aproximação será tão precisa quanto a anterior.

10

Mathematica, 20 bytes

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

A Rootfunção embutida do Mathematica fornece as soluções para uma equação polinomial f[x] == 0.

Explicação

#^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 *)

E / S de amostra

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

PS: Root[x^3-x-1,1]~N~#&funciona bem (apesar de não dizer que xé uma variável) para a mesma contagem de bytes.
Greg Martin

@ AndersKaseorg: Eu mudei essa regra porque estava claramente quebrada. Nenhuma resposta válida foi invalidada, mas algumas respostas (como esta) se tornaram 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]

saída

{1.32471795724474602596090885}


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

11
O resultado disso é no {{x -> 1.32...}}entanto. Convém verificar com ais se esse é um formato de saída válido.
Martin Ender

ok .. tudo corrigido, eu acho.
J42161217

Ainda é {1.32...}, na verdade, mas esse formato é provavelmente menos controverso.
Martin Ender

11
Tornei o desafio um pouco mais geral para que isso fosse válido, pois não pretendia proibir as soluções dos "primeiros x dígitos". Portanto, isso é válido agora, mesmo que não fosse antes.

6

sed , 67 60 (59 + 1) bytes

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

Experimente online!

+1 para a -Ebandeira (ERE em vez de BRE). Entrada e saída são unárias: entrada 11111 para x = 5, por exemplo, Saída é uma fração de dois números unários: a entrada 11111 mencionada acima produz a saída 11111/1111 (5/4 em decimal).

Aproxima o número do plástico como uma fração entre os elementos consecutivos da sequência Padovan .


11
FWIW, você não precisa de um espaço após o bcomando, mas pode reduzi -lo ainda mais usando o rótulo vazio ( :e bsem argumento). tio.run/#%23K05N@f@/…
Jordânia

Oh excelente. E posso salvar outros 4 bytes usando, em tvez de b, para que seja um salvamento bastante agradável. Obrigado :)
FireFly

5

Mathematica, 27 bytes

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

Usa uma aproximação truncada da forma de radical cúbico aninhado ³√ (1 + ³√ (1 + ³√ (1 + ...))) . Embora a saída sempre tenha casas decimais x-1 , o resultado é menos preciso do que isso, porque a expressão converge mais lentamente que um dígito por iteração ( x também é usado como o número de radicais aninhados que são calculados). Por exemplo, x = 100 fornece

_________________________________________________________________________
1.324717957244746025960908854478097340734404056901733364534015050302827850993693624204577670741656151

onde a parte sobreposta está correta.


Eu estava planejando escrever esse algoritmo dc, mas fiquei frustrado, porque acontece que ele não possui uma operação de raiz de cubo e aumentar um número para o poder ⅓ também não funciona :-( Pelo menos você sempre pode contar com Mathematica para ter builtins apropriados…

3
@ ais523 Na verdade, CubeRootmas ninguém tem bytes para isso.
Martin Ender

4

Oitava , 50 bytes

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

Experimente online!

Define uma função anônima, com no número desejado de dígitos da saída.

Esta resposta abusa que digitsretorna a configuração atual para o número de dígitos na aritmética de precisão variável. Isso significa que podemos apenas usá-lo em uma função anônima sem erros sobre 'Muitos argumentos de saída'.

Fora isso, é realmente simples: vpasolveé a abreviação de Aritmética de precisão variável, com a precisão definida pela última chamada de digits. Como vpaé um tipo de dados simbólico no Octave, que é banido de acordo com as especificações, envolvemos toda a função char(...)para obter a saída da string. Observe que em solvee vpasolve, o f==0está implícito, portanto r^3==r+1, foi substituído porr^3-r-1 (==0)


Fui e mudei a pergunta para que não proibisse respostas como essa (não era para isso).

@ ais523 Obrigado pela notificação!
Sanchises

4

MATL ( 27 28 bytes)

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

Minha primeira solução (27 bytes)

Experimente online!

Certamente não é o ideal, ainda estou me acostumando com o MATL.

Explicação:

Eu crio uma sequência Padovan até a entrada + 3 e depois encontro a proporção dos dois ú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 ρ

Saída de fração adequada (35 bytes) (28 bytes, @Sanchises):

No entanto, a primeira solução não atende à necessidade de precisão arbitrária, sendo o limite de ponto flutuante das configurações padrão do MATL. Então, ao invés de adicionar vários bytes para estender esta precisão, é mais simples para tomar a rota fração própria e escrever uma fração dos dois últimos números inteiros na (N-1) th e N º elementos da sequência Padovan truncado.

por exemplo "114/86"

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

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

Cortesia do usuário @Sanchises. :)

Experimente online!

Avaliação não iterativa:

Notavelmente, meu código mais curto para a versão 'exata' é (23 bytes):

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

Experimente online!

... mas não fornece precisão arbitrária. Gostaria de saber se alguém pode ajustar isso para cumprir as regras (use a entrada etc) e ainda adicionar menos de 5 bytes? : P


11
1+pode ser reduzido para Q. Com isso em mente, você pode substituir @)y@1+)+por apenas @tQh)s. Além disso, você pode usar Jpara indicar o final de uma matriz; e, finalmente, o MATL não faz distinção entre matrizes normais e matrizes de caracteres, para que você possa substituí-lo Ycpor h(você não precisa da funcionalidade extra de Yc). Isso fornece apenas 28 bytes: 7BG:"t@tQh)sh]tJ)V47hyJq)Vh&(observe &para evitar saída supérflua e substitua '/'por 47).
Sanchises

11
Kudos para o 7Bembora, muito melhor do que ingenuamente empurrandolllv
Sanchises

11
@DrQuarius A versão mais recente sempre pode ser encontrada neste link do GitHub
Luis Mendo

11
@DrQuarius Não, esse comportamento está presente nas especificações MATL bastante antigas que geralmente uso. Você realmente deve verificar a Tabela 3. Não só a área Jde transferência, por padrão 1j, contém , mas a área de transferência Ltambém contém muitas funções de indexação úteis (observe que 1jé igual a endMATL).
Sanchises

11
Além disso, não se preocupe, sou engenheiro mecânico. Eu acho que o MATL (AB) tem pouco uso fora de um ambiente científico, então acho que a maioria dos golfistas do MATL (AB) / Oitava são de fora do CS.
Sanchises

4

M , 15 14 bytes

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

Experimente online!

Algoritmo

Isso usa racionalidades e método de Newton. Especificamente, para a entrada x , as primeiras x iterações com o valor inicial x são aplicadas.

Estamos tentando encontrar uma raiz específica do polinômio p (t) = t³ - t - 1 . O método de Newton consegue isso pegando um valor inicial t 0 - suficientemente próximo de ρ - e definindo recursivamente uma sequência por
t n + 1 = t n - p (t n ) / p '(t n ) .

Como p '(t) = 3t² -1 , obtemos
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) .

Observe que a aproximação inicial x piora progressivamente à medida que x aumenta. Embora a saída para x = 3 seja um pouco menos precisa que a saída para x = 2 , como o método de Newton converge quadraticamente para ρ , isso não deve ser um problema para grandes valores de x .

Como 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.

Pena que você não pode usar ... µ¡...
Erik the Outgolfer



1

Carvão , 28 bytes

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

Experimente online! Link para o modo detalhado. Também aparentemente eu errei Dividee IntDivide: |
Usa o mesmo método que as respostas Python e JavaScript.


1

NewStack , 14 bytes

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

Demolir:

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

Como funciona:

A fórmula (2x 3 +1) / (3x 2 -1) deriva da simplificação do método de Newton para a equação x 3 = x + 1. Você pode encontrá-lo aqui . Repetindo esse processo, uma quantidade infinita de vezes converge para o número plástico. Sua taxa de convergência é bastante rápida, em torno de 2,6 decimais por iteração.

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 sequência Padovan, 27 25 17 bytes

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

Demolir:

¹                  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, escolhendo uma melhor estratégia de impressão

-8 bytes, escolhendo a melhor maneira de indexar a pilha

Como funciona:

À medida que a sequência Padovan continua, a proporção dos dois últimos elementos converge para o número do 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)%)

Usa a fórmula de raiz de cubo iterada. Isso é um pouco mais interessante, mas mais longo:

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

((f 10)1)
1.3247179361449652

“Você não pode presumir que a aritmética de ponto flutuante no seu idioma seja arbitrariamente precisa, mas deve usar sua precisão real (o que significa que a saída de um número de ponto flutuante só será possível em idiomas onde a precisão dos números de ponto flutuante pode seja controlado em tempo de execução). ”
Anders Kaseorg 16/17

Ooh, eu não percebi isso, que chatice. E implementar a raiz cúbica com o 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 da mesma forma que a resposta python superior. Não console.logfoi incluído porque se você executar f(x)no console, ele será registrado automaticamente.

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 a entrada esteja presente na pilha no início do programa, portanto, +3 bytes para o -vsinalizador.

Experimente online!

Efetivamente realiza uma pesquisa binária para restringir o valor de saída. Aumentar xaumenta o número de iterações a serem executadas.

Editar: cálculo refatorado ligeiramente para economizar 1 byte, versão 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

Usa essa fórmula recursiva .

Curiosamente, codificar o número e arredondá-lo fornece o mesmo 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

Usa essa fórmula trigonométrica .


Eu não acho que você pode usar carros alegóricos da TI-BASIC aqui: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)));};

Retorna o resultado como uma fração.

Explicação

Ele usa o método de Newton com x iterações para encontrar a raiz do polinômio p ^ 3-p-1 = 0. A fórmula é x_n = 1- (f (x_ (n-1))) / (f '(x_ (n-1))) e x_0 é o ponto de partida.

A derivada polinomial é 3p ^ 2-1, e digamos x_ (n-1) = b / c. Então, usando a fórmula acima, obtemos que x_n = (2 b ^ 3 + c ^ 3) / (3 b ^ 2 cc ^ 3). Digamos também que, partindo de 1, isso acontecerá quando x = 2, porque x> 1 e é um número inteiro. Código identificado e 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

como você pode ver h (2) deve ser 1,32 e não 1,33, por isso há algum erro nos últimos dígitos

Então haveria este 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)

Use a fórmula para resolver a equação da classe III do tipo x ^ 3-3 * p * x-2 * q = 0 no caso q ^ 2-p ^ 3> = 0 que é m = sqrt (q ^ 2- Dê sua nota! Dê sua nota! 2Comentários (2)

No nosso caso, r ^ 3-r-1 = 0, isso pode ser escrito como r ^ 3-3 * (1/3) r-2 * (1/2) = 0, então p = 1/3 q = 1/2 Qual é a raiz quadrada de 2? Matemática5 pontos

este que usa a iteração de Newton com o ponto inicial 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)

ele muda na função, digita o valor para obter um objetivo de n + 1 dígitos após o ponto flutuante. No final, o valor de dígitos () é atribuído novamente ao valor anterior.


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.