Metoda Newtona metodą Quinesów rekurencyjnych


32

Twoim zadaniem jest obliczenie pierwiastka kwadratowego z 2 za pomocą Metody Newtona - z lekkim zwrotem akcji. Twój program ma obliczyć iterację za pomocą metody Newtona i wygenerować kod źródłowy dla następnej iteracji (która musi być w stanie zrobić to samo).

Metoda Newtona jest dość wyczerpująco opisana na Wikipedii

Aby obliczyć pierwiastek kwadratowy 2 przy użyciu metody Newtona, należy:

  • Definiować f(x) = x^2 - 2
  • Definiować f'(x) = 2x
  • Zdefiniuj x[0](początkowe przypuszczenie)= 1
  • Definiować x[n+1] = x[n] - (f[n] / f'[n])

Każda iteracja przesunie się x [n] bliżej pierwiastka kwadratowego z dwóch. Więc -

  • 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
  • i tak dalej

Twój program będzie:

  • Oblicz, x[n]gdzie njest liczba uruchomień programu
  • Wyślij kod źródłowy do poprawnego programu w tym samym języku, który musi obliczyć x[n+1]i spełnić te same kryteria tego pytania.
  • Pierwszym wierszem kodu źródłowego musi być wynik obliczenia, odpowiednio skomentowany. Jeśli źródło wymaga czegoś konkretnego (np. Shebang) w pierwszym wierszu, wynik może zostać umieszczony w drugim wierszu.

Zauważ, że

  • Twój program musi wstępnie zgadywać x[0] = 1
  • Te standardowe Luki zastosowanie
  • Wszelkie wbudowane funkcje zasilania, pierwiastek kwadratowy lub xroot są zabronione
  • Twój program nie może akceptować żadnych danych wejściowych. Musi być całkowicie samodzielny.

Twój wynik to rozmiar początkowego programu w bajtach UTF-8. Najniższy wynik wygrywa.


Czy musimy zdefiniować funkcje, czy możemy uprościć pisząc x = x-(x*x-2)/(2*x)?
— Kyle Kanos

To uproszczenie wydaje mi się ważne. Tak długo, jak wykonuje obliczenia przy użyciu Metody Newtona
— lochok

Czy program wyświetla przybliżenie, czy tylko kod źródłowy? Czy może brać za swoje poprzednie rozwiązanie?
— Emily,

Musi wyprowadzić przybliżenie (skomentowane) w pierwszym wierszu, wraz z kodem źródłowym dla następnej iteracji. Zbliżenie może być poprzedzone shebangiem, jeśli język tego wymaga. Program (ani program, który produkuje) nie może przyjmować żadnych danych wejściowych.
— lochok

Odpowiedzi:


19

Common Lisp, 223 95 68 66

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

Teraz, gdy uważniej przeczytałem oświadczenie o problemie (dzięki, primo !), Zauważyłem, że pierwsza linia musi być wynikiem obliczeń, a nie, że musi zawierać wynik. Dlatego myślę, że moje wcześniejsze próby nie były zgodne z zasadami. Ten powinien.

Przykładowe zastosowanie (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)
$

Przeważnie testowałem z CCL, ale działa podobnie z SBCL i CLISP.
— jlahd

1
To bardziej, niż się spodziewałem. +1
— primo

17

Python 60 bajtów

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

Lekko uprościłem formułę, stosując następujące podstawienia:

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

Mam nadzieję, że to nie problem.

Program działa w następujący sposób:

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

itp.


Nie wiem, czy jest to zgodne z prawem, czy nie, ale możesz skrócić swój początkowy kod do g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 znaków.
— cjfaure

@Trimsty Myślę, że nieco problematyczne jest to, że 1) w rzeczywistości nie oblicza pierwszej iteracji i że 2) pierwszy wiersz nie zawiera bieżącego wyniku. Jak rozumiem opis problemu, zarówno oryginalny program, jak i późniejsze generacje powinny spełniać te kryteria.
— primo

13

CJam, 20 bajtów

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

Wypróbuj online.

Wydajność

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

Jak to działa

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
To imponujące. +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)

Jest to to samo co powyżej, w przypadku starszych przeglądarek.


1
Czasami jestem po prostu zaskoczony, jak prosty javascript może tworzyć różne rzeczy. +1
— patrz

To wydaje się być pozbawiony jakiejkolwiek mocy ( print, putstr, console.logitd.)
— primo

@primo - Gdy JavaScript jest uruchamiany w konsoli, zwracana wartość jest automatycznie drukowana.
— Derek 朕 會 功夫

@Derek 朕 會 功夫 Bardzo wiele języków można uruchamiać jako REPL - jest to wyrażenie, a nie pełny program. Zobacz: Standardowe „luki”, które nie są już śmieszne .
— primo

1
@Derek 朕 會 功夫 Opis problemu konkretnie prosi o program - w kilku miejscach. Dostarczony program nic nie robi. Świadek: i.stack.imgur.com/Te7Vf.png Powyższe jest wyrażeniem, którego wynikiem jest wyrażenie. Ma swoje zalety, ale nie jest programem.
— primo

6

Lua 129

Prawdopodobnie zbyt długo, ale Quine Lua jest do bani, ponieważ zagnieżdżenie [[ ]]jest przestarzałą funkcją. Ale działa niezależnie:

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)

Nieco przyjemniej jest sprawdzić, czy dodajesz znaki nowej linii zamiast dwukropków:

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 bajtów

Jest to tak okropne, jak przy tworzeniu quinesów (prawdopodobnie poprawię to, gdy będę miał lepsze pomysły). Liczba zmiennoprzecinkowa J jest ograniczona do 5 miejsc po przecinku, ale zastąpienie jej pierwszą linią x=:1xbyłoby ułamkiem z nieskończoną precyzją.

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

Kilka pierwszych iteracji:

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

Wyjaśnienie

((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
Uwielbiam, jak prosty jest ten program (na poważnie).
— patrz

Jeśli otrzymam więcej czasu, zobaczę, czy mogę zmodyfikować powyższe ustawienia dla Kona.
— Kyle Kanos

@KyleKanos Przynajmniej rotacja cyfr była dość podobna, ale nie znam Kony. Powodzenia! :)
— patrz

1%xjest taki sam jak %x. Zamiast tego (x%2)+1%xmożesz zrobić (%&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

Jak to często bywa, jest to prawie prosty port rozwiązania Python.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.