Método de Newton por Quines Recursivos


32

Sua tarefa é calcular a raiz quadrada de 2 usando o Método de Newton - com um ligeiro giro. Seu programa é calcular uma iteração usando o Método de Newton e gerar o código fonte para a seguinte iteração (que deve ser capaz de fazer o mesmo).

O método de Newton é descrito exaustivamente na Wikipedia

Para calcular a raiz quadrada 2 usando o método Newtons, você:

  • Definir f(x) = x^2 - 2
  • Definir f'(x) = 2x
  • Definir x[0](o palpite inicial)= 1
  • Definir x[n+1] = x[n] - (f[n] / f'[n])

Cada iteração se moverá x [n] para mais perto da raiz quadrada de dois. Tão -

  • x[0] = 1
  • x[1] = x[0] - f(x[0])/f'(x[0]) = 1 - (1 ^ 2 - 2) / (2 * 1) = 1.5
  • x[2] = x[1] - f(x[1])/f'(x[1]) = 1.5 - (1.5 ^ 2 - 2) / (2 * 1.5) = 1.416666667
  • x[3] = x[2] - f(x[2])/f'(x[1]) = 1.416666667 - (1.416666667 ^ 2 - 2) / (2 * 1.416666667) = 1.414215686
  • e assim por diante

Seu programa irá:

  • Calcular x[n]onde né a quantidade de vezes que o programa foi executado
  • Envie o código-fonte para um programa válido no mesmo idioma que deve calcular x[n+1]e atender aos mesmos critérios desta pergunta.
  • A primeira linha do código-fonte deve ser o resultado do cálculo, devidamente comentado. Se a fonte exigir algo específico (como um shebang) na primeira linha, o resultado poderá ser colocado na segunda linha.

Observe que

  • Seu programa deve usar uma estimativa inicial de x[0] = 1
  • As brechas padrão se aplicam
  • É proibida qualquer função embutida de poder, raiz quadrada ou xroot
  • Seu programa não deve aceitar nenhuma entrada. Deve ser totalmente independente.

Sua pontuação é do tamanho do seu programa inicial em bytes UTF-8. A pontuação mais baixa vence.


Temos que definir as funções ou podemos simplificar escrevendo x = x-(x*x-2)/(2*x)?
Kyle Kanos

Essa simplificação parece válida para mim. Enquanto ele executa o cálculo usando o método de Newton
lochok

O programa produz a aproximação ou apenas o código fonte? Pode tomar como entrada a solução anterior?
Emily

Ele deve gerar a aproximação (comentada) na primeira linha, com o código fonte para a próxima iteração. A aproximação pode ser precedida por um shebang se o idioma exigir. O programa (nem o programa que produz) não deve aceitar nenhuma entrada.
lochok

Respostas:


19

Lisp comum, 223 95 68 66

(#1=(lambda(x p)(format t"~S~%~S"p`(,x',x,(+(/ p 2)(/ p)))))'#1#1)

Agora que li a declaração do problema com mais cuidado (obrigado, primo !), Notei que a primeira linha deve ser o resultado do cálculo, não que ela precise conter o resultado. Portanto, acho que minhas tentativas anteriores não seguiram completamente as regras. Este deveria.

Exemplo de uso (SBCL 1.1.15):

$ sbcl --script nq.lisp | tee nq2.lisp
1
((LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 '(LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P))))) 3/2)
$ sbcl --script nq2.lisp | tee nq3.lisp
3/2
((LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 '(LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P))))) 17/12)
$ sbcl --script nq3.lisp | tee nq4.lisp
17/12
((LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 '(LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P))))) 577/408)
$ sbcl --script nq4.lisp | tee nq5.lisp
577/408
((LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 '(LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 665857/470832)
$ sbcl --script nq5.lisp | tee nq6.lisp
665857/470832
((LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 '(LAMBDA (X P) (FORMAT T "~S~%~S" P `(,X ',X ,(+ (/ P 2) (/ P)))))
 886731088897/627013566048)
$

Venho testando principalmente com o CCL, mas funciona da mesma forma com o SBCL e o CLISP.
jlahd

11
É mais como eu esperava. +1
primo

17

Python 60 bytes

x=1.
o='x=%s\no=%r;print o%%(x/2+1/x,o)';print o%(x/2+1/x,o)

Simplifiquei ligeiramente a fórmula, usando as seguintes substituições:

  x-(x²-2)/(2x)
= (2x²)/(2x)-(x²-2)/(2x)
= (2x²-x²+2)/(2x)
= (x²+2)/(2x)
= (x+2/x)/2
= x/2+1/x

Espero que isso não seja um problema.

O programa continua da seguinte maneira:

$ python newton-quine.py
x=1.5
o='x=%s\no=%r;print o%%(x/2+1/x,o)';print o%(x/2+1/x,o)

$ python newton-quine.py
x=1.41666666667
o='x=%s\no=%r;print o%%(x/2+1/x,o)';print o%(x/2+1/x,o)

$ python newton-quine.py
x=1.41421568627
o='x=%s\no=%r;print o%%(x/2+1/x,o)';print o%(x/2+1/x,o)

$ python newton-quine.py
x=1.41421356237
o='x=%s\no=%r;print o%%(x/2+1/x,o)';print o%(x/2+1/x,o)

etc.


Não sei se isso é legal ou não, mas você pode encurtar seu código inicial para g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 caracteres.
cjfaure

@ Trimsty Eu acho que é um pouco problemático que 1) na verdade não calcule a primeira iteração e que 2) a primeira linha não contém o resultado atual. Pelo que entendi a descrição do problema, o programa original e as gerações posteriores devem atender a esses critérios.
Primo

13

CJam, 20 bytes

1
{\d_2/1@/+p"_~"}_~

Experimente online.

Saída

$ cjam <(echo -e '1\n{\d_2/1@/+p"_~"}_~'); echo
1.5
{\d_2/1@/+p"_~"}_~
$ cjam <(cjam <(echo -e '1\n{\d_2/1@/+p"_~"}_~')); echo
1.4166666666666665
{\d_2/1@/+p"_~"}_~
$ cjam <(cjam <(cjam <(echo -e '1\n{\d_2/1@/+p"_~"}_~'))); echo
1.4142156862745097
{\d_2/1@/+p"_~"}_~
$ cjam <(cjam <(cjam <(cjam <(echo -e '1\n{\d_2/1@/+p"_~"}_~')))); echo
1.4142135623746899
{\d_2/1@/+p"_~"}_~

Como funciona

1       " Push the initial guess.                                                 ";
{       "                                                                         ";
  \d    " Swap the code block with the initial guess and cast to Double.          ";
  _2/   " Duplicate the initial guess and divide the copy by 2.                   ";
  1@/   " Push 1, rotate the initial guess on top and divide.                     ";
  +p    " Add the quotients and print.                                            ";
  "_~"  " Push the string '_~'.                                                   ";
}       "                                                                         ";
_~      " Duplicate the code block (to leave a copy on the stack) and execute it. ";

2
Bem, isso é impressionante. +1
Kyle Kanos

8

ECMAScript 6, 38 36

(f=x=>"(f="+f+")("+(x/2+1/x)+")")(1)
(f=x=>"(f="+f+")("+(x/2+1/x)+")")(1.5)
(f=x=>"(f="+f+")("+(x/2+1/x)+")")(1.4166666666666665)
(f=x=>"(f="+f+")("+(x/2+1/x)+")")(1.4142156862745097)
(f=x=>"(f="+f+")("+(x/2+1/x)+")")(1.4142135623746899)

JavaScript, 51

(function f(x){return "("+f+")("+(x/2+1/x)+")"})(1)

É o mesmo que acima, para navegadores mais antigos.


11
Às vezes, fico impressionado com o simples javascript que pode fazer as coisas. +1
veja

Este parece ser falta qualquer tipo de saída ( print, putstr, console.log, etc.).
Primo

@primo - Quando o JavaScript é executado em um console, o valor retornado é automaticamente impresso.
Derek朕會功夫

@Derek 功夫 會 功夫 Muitas linguagens podem ser executadas como REPL - esta é uma expressão e não um programa completo. Veja: “brechas” padrão que não são mais engraçadas .
Primo

11
@Derek 功夫 會 功夫 A descrição do problema solicita especificamente um programa - em vários lugares. O programa fornecido não faz nada. Testemunha: i.stack.imgur.com/Te7Vf.png O texto acima é uma expressão que é avaliada como uma expressão. Ele tem mérito próprio, mas não é um programa.
primo

6

Lua 129

Provavelmente, por muito tempo, mas o lua quine [[ ]]é uma porcaria porque o aninhado é um recurso obsoleto. Mas funciona independentemente:

x=1.0;x=x/2.+1./x;l=[[io.write('x=',x,';x=x/2.+1./x;l=[','[',l,']','];',l)]];io.write('x=',x,';x=x/2.+1./x;l=[','[',l,']','];',l)

É um pouco melhor ver se você adiciona novas linhas em vez de dois pontos:

x=1.0
x=x/2.+1./x
l=[[io.write('x=',x,'\nx=x/2.+1./x\nl=[','[',l,']','];',l)]];io.write('x=',x,'\nx=x/2.+1./x\nl=[','[',l,']','];',l)

4

J - 102 88 bytes

Isso é tão horrível quanto eu estou fazendo quines (provavelmente vou revisar isso quando tiver melhores idéias). Os carros alegóricos de J são limitados a 5 casas decimais, mas substituir a primeira linha por x=:1xela seria uma fração com precisão infinita.

Edit 1: I got better idea. Also added the explanation.

x=:1
((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'x=:((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'''

Primeiras iterações:

x=:1.5
((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'x=:((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'''

x=:1.41667
((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'x=:((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'''

x=:1.41422
((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'x=:((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'''

Explicação

((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'x=:((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:)'''
((3&{.,[:":(x%2)+1%x"_),:3&}.,],{:,{:) The quine-function
                         3&}.,],{:,{:  Build the second row
                         3&}.          Get everything but the first 3 characters from the string
                             ,]        Get the whole string and concat
                               ,{:     Get the last item (') and concat
                                  ,{:  -||-
 (3&{.,[:":(x%2)+1%x"_)                Build the first row
       [:":(x%2)+1%x"_                 Calculate x/2 + 1/x (stolen from Pythoneer) and stringify
  3&{.                                 Take the first 3 characters from the string (x=:)
      ,                                Concatenate 'x=:' and the result
                       ,:              Concatenate the two rows

11
Eu realmente amo o quão simples este programa é (para falar a sério).
seequ

Se eu tiver mais tempo, vou ver se posso modificar o que foi dito acima para o Kona.
precisa

@KyleKanos Pelo menos a coisa de rotação de dígitos era semelhante o suficiente, mas eu não conheço Kona. Boa sorte! :)
Veja

1%xé o mesmo que %x. Em vez de (x%2)+1%x, você pode fazer (%&2+%)x.
Conor O'Brien

3

Ruby, 65

x=1.0
puts"x=#{x/2+1/x}",<<'1'*2,1
puts"x=#{x/2+1/x}",<<'1'*2,1
1

Como muitas vezes acontece, essa é quase uma porta direta da solução Python.

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.