Méthode Newtons par Recinesive Quines

32

Votre tâche consiste à calculer la racine carrée de 2 en utilisant la méthode de Newton - avec une légère torsion. Votre programme consiste à calculer une itération à l'aide de la méthode de Newton et à générer le code source de l'itération suivante (qui doit pouvoir faire de même).

La méthode de Newton est décrite de manière assez exhaustive sur Wikipedia

Pour calculer la racine carrée 2 à l'aide de la méthode Newtons, vous:

  • Définir f(x) = x^2 - 2
  • Définir f'(x) = 2x
  • Définir x[0](la supposition initiale)= 1
  • Définir x[n+1] = x[n] - (f[n] / f'[n])

Chaque itération rapproche x [n] de la racine carrée de deux. Alors -

  • 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
  • etc

Votre programme:

  • Calculez x[n]où se ntrouve le nombre d'exécutions du programme
  • Sortie du code source dans un programme valide dans la même langue qui doit calculer x[n+1]et satisfaire les mêmes critères de cette question.
  • La première ligne du code source doit être le résultat du calcul, correctement commenté. Si la source nécessite quelque chose de particulier (comme un shebang) sur la première ligne, le résultat peut être mis sur la deuxième ligne.

Notez que

  • Votre programme doit utiliser une estimation initiale de x[0] = 1
  • Les échappatoires standard s'appliquent
  • Toutes les fonctions de puissance, racine carrée ou xroot intégrées sont interdites
  • Votre programme ne doit accepter aucune entrée quelle qu'elle soit. Il doit être entièrement autonome.

Votre score est la taille de votre programme initial en octets UTF-8. Le score le plus bas l'emporte.

lochok
la source
Faut-il définir les fonctions, ou peut-on simplifier en écrivant x = x-(x*x-2)/(2*x)?
Kyle Kanos
Cette simplification me semble valable. Tant qu'il effectue le calcul en utilisant la méthode de Newton
lochok
Le programme génère-t-il l'approximation ou simplement le code source? Peut-il prendre comme entrée la solution précédente?
Emily
Il doit afficher l'approximation (commentée) sur la première ligne, avec le code source pour la prochaine itération. L'approximation peut être précédée d'un shebang si la langue l'exige. Le programme (ni le programme qu'il produit) ne doit accepter aucune entrée.
lochok

Réponses:

19

Lisp commun, 223 95 68 66

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

Maintenant que j'ai lu l'énoncé du problème plus attentivement (merci, primo !), J'ai remarqué que la première ligne doit être le résultat du calcul, pas qu'elle doit contenir le résultat. Ainsi, je pense que mes tentatives précédentes n'ont pas tout à fait suivi les règles. Celui-ci devrait.

Exemple d'utilisation (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)
$
jlahd
la source
J'ai principalement testé avec CCL, mais cela fonctionne de manière similaire avec SBCL et CLISP.
jlahd
1
C'est plus comme je m'y attendais. +1
primo
17

Python 60 octets

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

J'ai légèrement simplifié la formule, en utilisant les substitutions suivantes:

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

J'espère que ce n'est pas un problème.

Le programme se déroule de la manière suivante:

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

primo
la source
Je ne sais pas si c'est légal ou non, mais vous pouvez raccourcir votre code initial à g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 caractères.
cjfaure
@Trimsty Je pense que c'est un peu problématique que 1) il ne calcule pas réellement la première itération, et que 2) la première ligne ne contienne pas le résultat actuel. Si je comprends bien la description du problème, le programme d'origine et les générations ultérieures devraient satisfaire à ces critères.
primo
13

CJam, 20 octets

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

Essayez-le en ligne.

Sortie

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

Comment ça marche

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. ";
Dennis
la source
2
Eh bien, c'est impressionnant. +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)

C'est la même chose que ci-dessus, pour les navigateurs plus anciens.

Zaq
la source
1
Parfois, je suis juste étonné de voir à quel point le javascript simple peut faire les choses. +1
seequ
Cela semble être dépourvu de toute sorte de sortie ( print, putstr, console.log, etc.).
primo
@primo - Lorsque JavaScript est exécuté dans une console, la valeur renvoyée est automatiquement imprimée.
Derek 朕 會 功夫
@Derek 朕 會 功夫 De très nombreuses langues peuvent être exécutées en tant que REPL - il s'agit d'une expression et non d'un programme complet. Voir: les «failles» standard qui ne sont plus drôles .
primo
1
@Derek 朕 會 功夫 La description du problème demande spécifiquement un programme - à plusieurs endroits. Le programme fourni ne fait rien. Témoin: i.stack.imgur.com/Te7Vf.png Ce qui précède est une expression qui s'évalue en une expression. Il a son propre mérite, mais ce n'est pas un programme.
primo
6

Lua 129

Probablement beaucoup trop longtemps, mais le quine Lua est nul parce que l'imbriqué [[ ]]est une fonctionnalité obsolète. Mais cela fonctionne malgré tout:

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)

C'est un peu plus agréable de voir si vous ajoutez des sauts de ligne au lieu des deux points:

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)
Kyle Kanos
la source
4

J - 102 88 octets

C'est aussi horrible que de faire des quines (je réviserai probablement cela quand j'aurai de meilleures idées). Les flottants de J sont limités à 5 décimales, mais en remplaçant la première ligne par x=:1xce serait une fraction avec une précision infinie.

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

Premières itérations:

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

Explication

((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
voir
la source
1
J'adore la simplicité de ce programme (pour les sérieux).
seequ
Si j'ai plus de temps, je vais voir si je peux modifier ce qui précède pour Kona.
Kyle Kanos
@KyleKanos Au moins, le machin de rotation des chiffres était assez similaire, mais je ne connais pas Kona. Bonne chance! :)
seequ
1%xest le même que %x. Au lieu de cela (x%2)+1%x, vous pouvez le faire (%&2+%)x.
Conor O'Brien
3

Ruby, 65 ans

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

Comme cela arrive trop souvent, il s'agit presque d'un port direct de la solution Python.

histocrate
la source