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.