Metodo Newton di Quines ricorsive


32

Il tuo compito è calcolare la radice quadrata di 2 usando il Metodo di Newton - con una leggera variazione. Il tuo programma è di calcolare un'iterazione usando il metodo di Newton e di generare il codice sorgente per la seguente iterazione (che deve essere in grado di fare lo stesso).

Il metodo di Newton è descritto in modo abbastanza esaustivo su Wikipedia

Per calcolare la radice quadrata 2 usando il metodo Newton, devi:

  • Definire f(x) = x^2 - 2
  • Definire f'(x) = 2x
  • Definisci x[0](ipotesi iniziale)= 1
  • Definire x[n+1] = x[n] - (f[n] / f'[n])

Ogni iterazione si sposterà x [n] più vicino alla radice quadrata di due. Così -

  • 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 così via

Il tuo programma dovrà:

  • Calcola x[n]dove nè la quantità di volte che il programma è stato eseguito
  • Invia il codice sorgente a un programma valido nella stessa lingua che deve calcolare x[n+1]e soddisfare gli stessi criteri di questa domanda.
  • La prima riga del codice sorgente deve essere il risultato del calcolo, opportunamente commentato. Se la fonte richiede qualcosa di particolare (come uno shebang) sulla prima riga, il risultato può essere inserito sulla seconda riga.

Nota che

  • Il tuo programma deve utilizzare un'ipotesi iniziale di x[0] = 1
  • Si applicano le scappatoie standard
  • È vietata qualsiasi funzione incorporata di potenza, radice quadrata o xroot
  • Il tuo programma non deve accettare alcun input. Deve essere completamente autonomo.

Il tuo punteggio è la dimensione del tuo programma iniziale in byte UTF-8. Vince il punteggio più basso.


Dobbiamo definire le funzioni o possiamo semplificare scrivendo x = x-(x*x-2)/(2*x)?
Kyle Kanos,

Questa semplificazione mi sembra valida. Finché esegue il calcolo usando il metodo di Newton
lochok,

Il programma genera l'approssimazione o solo il codice sorgente? Può prendere come input la soluzione precedente?
Emily,

Deve generare l'approssimazione (commentata) sulla prima riga, con il codice sorgente per la successiva iterazione. L'approssimazione può essere preceduta da uno shebang se la lingua lo richiede. Il programma (né il programma che produce) non deve accettare alcun input.
Lochok,

Risposte:


19

Lisp comune, 223 95 68 66

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

Ora che ho letto più attentamente la dichiarazione del problema (grazie, primo !) Ho notato che la prima riga deve essere il risultato del calcolo, non che deve contenere il risultato. Quindi, penso che i miei precedenti tentativi non abbiano del tutto seguito le regole. Questo dovrebbe.

Esempio di utilizzo (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)
$

Ho testato principalmente con CCL, ma funziona in modo simile sia con SBCL che con CLISP.
jlahd

1
È più come mi aspettavo. +1
primo

17

Python 60 byte

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

Ho semplificato leggermente la formula, usando le seguenti sostituzioni:

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

Spero non sia un problema.

Il programma procede nel modo seguente:

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

eccetera.


Non so se questo è legale o no, ma puoi abbreviare il tuo codice iniziale a g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 caratteri.
cjfaure,

@Trimsty Penso che sia leggermente problematico il fatto che 1) in realtà non calcoli la prima iterazione e che 2) la prima riga non contenga il risultato corrente. Come ho capito la descrizione del problema, sia il programma originale che le generazioni successive dovrebbero soddisfare questi criteri.
primo

13

CJam, 20 byte

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

Provalo online.

Produzione

$ 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"_~"}_~

Come funziona

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
Bene, è 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)

È lo stesso del precedente, per i browser più vecchi.


1
A volte sono solo stupito di come javascript semplice possa fare le cose. +1
seequ

Questo sembra essere priva di qualsiasi tipo di output ( print, putstr, console.log, ecc).
primo

@primo: quando JavaScript viene eseguito in una console, il valore restituito viene stampato automaticamente.
Derek 朕 會 功夫

@Derek 朕 會 功夫 È possibile eseguire molte lingue come REPL - questa è un'espressione e non un programma completo. Vedi: "scappatoie" standard che non sono più divertenti .
primo

1
@Derek 朕 會 功夫 La descrizione del problema richiede specificamente un programma - in diversi punti. Il programma fornito non fa nulla. Testimone: i.stack.imgur.com/Te7Vf.png Quanto sopra è un'espressione che valuta un'espressione. Ha un merito a sé stante, ma non è un programma.
primo

6

Lua 129

Probabilmente troppo a lungo, ma il Lua quine fa schifo perché il nidificato [[ ]]è una funzione deprecata. Ma funziona a prescindere:

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)

È un po 'più bello vedere se aggiungi nuove righe invece di due punti:

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 byte

È orribile quanto sto facendo quines (probabilmente lo rivedrò quando avrò idee migliori). I float di J sono limitati a 5 cifre decimali, ma sostituendo la prima riga con x=:1xessa sarebbe una frazione con precisione 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&}.,],{:,{:)'''

Prime iterazioni:

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&}.,],{:,{:)'''

Spiegazione

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

1
In realtà adoro quanto sia semplice questo programma (sul serio).
Seequ,

Se avrò più tempo, vedrò se posso modificare quanto sopra per Kona.
Kyle Kanos,

@KyleKanos Almeno il dispositivo di rotazione delle cifre era abbastanza simile, ma non conosco Kona. In bocca al lupo! :)
seequ

1%xè lo stesso di %x. Invece di (x%2)+1%x, puoi farlo (%&2+%)x.
Conor O'Brien,

3

Ruby, 65 anni

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

Come troppo spesso accade, questa è quasi una porta diretta della soluzione Python.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.