Newton-Methode nach rekursiven Quines


32

Ihre Aufgabe ist es, die Quadratwurzel von 2 mit der Newtonschen Methode zu berechnen - mit einer leichten Drehung. Ihr Programm berechnet eine Iteration nach der Newton-Methode und gibt den Quellcode für die folgende Iteration aus (die dazu in der Lage sein muss).

Newtons Methode ist auf Wikipedia ziemlich ausführlich beschrieben

So berechnen Sie die Quadratwurzel 2 mit der Newton-Methode:

  • Definieren f(x) = x^2 - 2
  • Definieren f'(x) = 2x
  • Definieren x[0](die anfängliche Vermutung)= 1
  • Definieren x[n+1] = x[n] - (f[n] / f'[n])

Jede Iteration rückt x [n] näher an die Quadratwurzel von zwei. So -

  • 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
  • und so weiter

Ihr Programm wird:

  • Berechnen Sie, x[n]wo nist die Höhe der Zeit , das Programm ausgeführt wurde
  • Den Quellcode an ein gültiges Programm in derselben Sprache x[n+1]ausgeben, das die gleichen Kriterien für diese Frage berechnen und erfüllen muss .
  • Die erste Zeile des Quellcodes muss das korrekt kommentierte Berechnungsergebnis sein. Wenn die Quelle in der ersten Zeile etwas Bestimmtes (wie einen Schebang) erfordert, kann das Ergebnis in die zweite Zeile gestellt werden.

Beachten Sie, dass

  • Ihr Programm muss eine erste Schätzung von verwenden x[0] = 1
  • Es gelten die Standard-Regelungslücken
  • Alle eingebauten Power-, Quadratwurzel- oder Xroot-Funktionen sind verboten
  • Ihr Programm darf keinerlei Eingaben akzeptieren. Es muss völlig in sich geschlossen sein.

Ihre Punktzahl entspricht der Größe Ihres ursprünglichen Programms in UTF-8-Bytes. Die niedrigste Punktzahl gewinnt.


Müssen wir die Funktionen definieren oder können wir sie durch Schreiben vereinfachen x = x-(x*x-2)/(2*x)?
Kyle Kanos

Diese Vereinfachung scheint mir gültig zu sein. Solange die Berechnung nach der Newtonschen Methode durchgeführt wird
lochok

Gibt das Programm die Annäherung oder nur den Quellcode aus? Kann es die vorherige Lösung als Eingabe nehmen?
Emily

Es muss die Annäherung (kommentiert) in der ersten Zeile mit dem Quellcode für die nächste Iteration ausgeben. Der Annäherung kann ein Knall vorausgehen, wenn die Sprache dies erfordert. Das Programm (oder das Programm, das es erstellt) darf keine Eingaben akzeptieren.
Lochok

Antworten:


19

Common Lisp, 223 95 68 66

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

Nachdem ich die Problembeschreibung genauer gelesen habe (danke, primo !) , Ist mir aufgefallen, dass die erste Zeile das Ergebnis einer Berechnung sein muss und nicht das Ergebnis enthalten muss . Daher glaube ich, dass meine früheren Versuche nicht ganz den Regeln entsprachen. Dieser sollte.

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

Ich habe hauptsächlich mit CCL getestet, aber es funktioniert ähnlich mit SBCL und CLISP.
Jlahd

1
Das ist eher so, wie ich es erwartet hatte. +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)

Ich habe die Formel mit den folgenden Ersetzungen leicht vereinfacht:

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

Ich hoffe, das ist kein Problem.

Das Programm läuft folgendermaßen ab:

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


Ich weiß nicht, ob dies legal ist oder nicht, aber Sie können Ihren ursprünglichen Code auf g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 Zeichen verkürzen .
cjfaure

@Trimsty Ich finde es etwas problematisch, dass 1) die erste Iteration nicht berechnet wird und 2) die erste Zeile nicht das aktuelle Ergebnis enthält. Nach meinem Verständnis der Problembeschreibung sollten sowohl das ursprüngliche Programm als auch spätere Generationen diese Kriterien erfüllen.
Primo

13

CJam, 20 Bytes

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

Probieren Sie es online aus.

Ausgabe

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

Wie es funktioniert

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
Das ist beeindruckend. +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)

Dies ist dasselbe wie oben für ältere Browser.


1
Manchmal wundere ich mich nur, wie einfach Javascript Dinge machen kann. +1
siehe auch

Dies scheint jede Art von Ausgabe zu fehlen ( print, putstr, console.log, etc.).
Primo

@primo - Wenn JavaScript in einer Konsole ausgeführt wird, wird der zurückgegebene Wert automatisch gedruckt.
Derek 朕 朕 功夫

@Derek 朕 會 會 Sehr viele Sprachen können als REPL ausgeführt werden - dies ist ein Ausdruck und kein vollständiges Programm. Siehe: Standard "Schlupflöcher", die nicht mehr lustig sind .
Primo

1
@Derek 朕 會 會 In der Problembeschreibung wird gezielt nach einem Programm gefragt - an mehreren Stellen. Das mitgelieferte Programm macht nichts. Witness: i.stack.imgur.com/Te7Vf.png Das Obige ist ein Ausdruck, der zu einem Ausdruck ausgewertet wird. Es hat seine eigenen Verdienste, aber es ist kein Programm.
Primo

6

Lua 129

Wahrscheinlich viel zu lang, aber die Lua quine ist scheiße, weil das verschachtelte [[ ]]Feature veraltet ist. Aber es funktioniert trotzdem:

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)

Es ist ein bisschen schöner zu sehen, ob Sie Zeilenumbrüche anstelle von Doppelpunkten hinzufügen:

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

Das ist so schrecklich, wie ich Quines mache (ich werde das wahrscheinlich korrigieren, wenn ich bessere Ideen bekomme). Die Gleitkommazahlen von J sind auf 5 Dezimalstellen begrenzt, aber durch Ersetzen der ersten Zeile x=:1xwäre dies ein Bruch mit unendlicher Genauigkeit.

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

Erste Iterationen:

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

Erläuterung

((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
Ich mag es wirklich, wie einfach dieses Programm ist (für ernsthafte).
Siehe auch

Wenn ich mehr Zeit habe, werde ich sehen, ob ich das oben genannte für Kona ändern kann.
Kyle Kanos

@KyleKanos Zumindest das Digit-Rotation-Ding war ähnlich genug, aber ich kenne Kona nicht. Viel Glück! :)
Siehe auch

1%xist das gleiche wie %x. Stattdessen (x%2)+1%xkönnen Sie tun (%&2+%)x.
Conor O'Brien

3

Rubin, 65

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

Wie so oft ist dies fast ein direkter Port der Python-Lösung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.