Özyinelemeli Quines ile Newton Yöntemi


32

Göreviniz Newton'un Yöntemini kullanarak 2'nin karekökünü hesaplamaktır - hafif bir bükülme ile. Programınız, Newton'un Yöntemini kullanarak bir yineleme hesaplamak ve aşağıdaki yinelemenin kaynak kodunu çıkarmaktır (aynı şeyi yapabilmelidir).

Newton'un yöntemi Wikipedia'da oldukça ayrıntılı bir şekilde tarif edilmiştir.

Newtons yöntemini kullanarak karekök 2'yi hesaplamak için:

  • Tanımlamak f(x) = x^2 - 2
  • Tanımlamak f'(x) = 2x
  • Tanımla x[0](ilk tahmin)= 1
  • Tanımlamak x[n+1] = x[n] - (f[n] / f'[n])

Her yineleme, x [n] 'in kareköküne yaklaştıracaktır. Yani -

  • 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
  • ve bunun gibi

Programınız:

  • Programın kaç kez çalıştırıldığını x[n]nerede hesaplan
  • Kaynak kodu x[n+1], bu sorunun aynı kriterlerini hesaplamak ve karşılamak için aynı dilde geçerli bir programa gönderin .
  • Kaynak kodun ilk satırı, düzgün bir şekilde yorumlanmış hesaplama sonucu olmalıdır. Kaynak ilk satırda belirli bir şeye (bir shebang gibi) ihtiyaç duyuyorsa, sonuç ikinci satıra yerleştirilebilir.

Bunu not et

  • Programınız ilk bir tahmin kullanmalı x[0] = 1
  • Standart Boşluk Doldurma uygulamak
  • Herhangi bir yerleşik güç, karekök veya xroot işlevler yasaktır
  • Programınız herhangi bir girişi kabul etmemelidir. Tamamen kendi kendine yeten olmalı.

Puanınız, ilk programınızın UTF-8 bayt cinsinden boyutudur. En düşük puan kazanır.


İşlevleri tanımlamalı mıyız yoksa yazarak sadeleştirebilir miyiz x = x-(x*x-2)/(2*x)?
Kyle Kanos

Bu sadeleştirme benim için geçerli görünüyor. Newton'un Metodunu kullanarak hesaplama yaptığı
sürece

Program yaklaşımı mı yoksa sadece kaynak kodu mu veriyor? Önceki çözümü girdi olarak alabilir mi?
Emily

Bir sonraki yinelemenin kaynak koduyla birlikte ilk satırdaki yaklaşımı (yorumlanmış) çıkarması gerekir. Dil gerektiriyorsa, bu yaklaşımdan önce bir shebang gelebilir. Program (ürettiği program) herhangi bir girişi kabul etmemelidir.
lochok

Yanıtlar:


19

Common Lisp, 223 95 68 66

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

Şimdi sorun bildirimini daha dikkatli okudum (teşekkürler, primo !) İlk satırın sonucu içermesi gerektiğini değil, hesaplamanın sonucu olması gerektiğini fark ettim . Bu nedenle, daha önceki girişimlerimin kurallara tam olarak uymadığını düşünüyorum. Bu olmalı.

Örnek kullanım (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)
$

Çoğunlukla CCL ile test yapıyorum, ancak hem SBCL hem de CLISP ile benzer şekilde çalışıyor.
jlahd

1
Bu daha çok umduğum gibi. +1
primo

17

Python 60 bayt

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

Aşağıdaki ikameleri kullanarak formülü biraz basitleştirdim:

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

Umarım bu bir sorun değildir.

Program aşağıdaki şekilde ilerler:

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

vb.


Bunun yasal olup olmadığını bilmiyorum, ancak ilk kodunuzu g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 karaktere kadar kısaltabilirsiniz .
cjfaure

@Trimsty 1) ilk yinelemeyi aslında hesaplamaması ve 2) ilk satırın mevcut sonucu içermemesi biraz sorunlu olduğunu düşünüyorum. Sorunun tanımını anladığım gibi, hem orijinal program hem de daha sonraki nesiller bu kriterleri karşılamalıdır.
primo

13

CJam, 20 bayt

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

Çevrimiçi deneyin.

Çıktı

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

Nasıl çalışır

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
Bu etkileyici. +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)

Bu, eski tarayıcılar için yukarıdakiyle aynıdır.


1
Bazen, javascript'in işleri nasıl basitleştirdiğini görünce şaşırdım. +1
seequ

Bu (çıktının her türlü eksik gibi görünüyor print, putstr, console.logvb.)
primo

@primo - Bir konsolda JavaScript çalıştırıldığında, döndürülen değer otomatik olarak yazdırılır.
Derek 朕

@Derek 朕 會 功夫 Pek çok dil REPL olarak çalıştırılabilir - bu bir ifadedir, tam bir program değildir. Bakınız: Artık komik olmayan standart “boşluklar” .
primo

1
@Derek 朕 會 problem Problem tanımı özellikle bir program için - birkaç yerde soruyor. Sağlanan program hiçbir şey yapmaz. Tanık: i.stack.imgur.com/Te7Vf.png Yukarıdaki, bir ifadeyi değerlendiren bir ifadedir. Kendi yararına sahip, ancak bir program değil.
primo,

6

Lua 129

Muhtemelen çok uzun, ama Lua quine berbat çünkü iç içe itiraz edilmiş [[ ]]bir özellik. Ama ne olursa olsun çalışır:

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)

İki nokta yerine yeni satır ekleyip eklemediğinizi görmek biraz daha güzel:

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 bayt

Bu benim quine yaptığım kadar korkunç (daha iyi fikirler aldığımda muhtemelen bunu gözden geçireceğim). J yüzer 5 ondalık basamak ile sınırlıdır, ancak ilk satırı onunla değiştirerek x=:1xsonsuz hassasiyetle bir kesir olacaktır.

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

İlk birkaç yineleme:

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

açıklama

((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
Aslında bu programın ne kadar basit olduğunu seviyorum (ciddi için).
seequ,

Daha fazla zaman alırsam, yukarıdaki Kona için değişiklik yapıp yapamayacağımı göreceğim.
Kyle Kanos

@KyleKanos En azından rakam-dönme-şeyi yeterince benzerdi, ama Kona'yı tanımıyorum. İyi şanslar! :)
seequ

1%xaynıdır %x. Bunun yerine (x%2)+1%xyapabilirsin (%&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

Çok sık olduğu gibi, bu Python çözümünün neredeyse düz bir limanı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.