วิธีการของนิวตันโดยการเรียกซ้ำ


32

งานของคุณคือการคำนวณสแควร์รูทของ 2 โดยใช้วิธีของนิวตัน - ด้วยการบิดเล็กน้อย โปรแกรมของคุณคือการคำนวณการวนซ้ำโดยใช้วิธีของนิวตันและเอาท์พุทซอร์สโค้ดสำหรับการทำซ้ำต่อไปนี้ (ซึ่งจะต้องทำเช่นเดียวกัน)

วิธีการของนิวตันได้รับการอธิบายอย่างละเอียดถี่ถ้วนในWikipedia

ในการคำนวณสแควร์รูท 2 โดยใช้วิธีของนิวตันคุณ:

  • กำหนด f(x) = x^2 - 2
  • กำหนด f'(x) = 2x
  • กำหนดx[0](การเดาเริ่มต้น)= 1
  • กำหนด x[n+1] = x[n] - (f[n] / f'[n])

การวนซ้ำแต่ละครั้งจะย้าย x [n] ใกล้กับสแควร์รูทของสอง ดังนั้น -

  • 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
  • และอื่น ๆ

โปรแกรมของคุณจะ:

  • คำนวณx[n]โดยที่nจำนวนครั้งที่โปรแกรมถูกเรียกใช้
  • เอาท์พุทซอร์สโค้ดไปยังโปรแกรมที่ถูกต้องในภาษาเดียวกันซึ่งจะต้องคำนวณx[n+1]และตอบสนองเกณฑ์เดียวกันของคำถามนี้
  • บรรทัดแรกของซอร์สโค้ดจะต้องเป็นผลการคำนวณแสดงความคิดเห็นอย่างถูกต้อง หากแหล่งข้อมูลต้องการบางสิ่งบางอย่าง (เช่น Shebang) ในบรรทัดแรกผลลัพธ์อาจถูกวางในบรรทัดที่สอง

สังเกตได้ว่า

  • โปรแกรมของคุณต้องใช้การคาดเดาเริ่มต้น x[0] = 1
  • ช่องโหว่มาตรฐานใช้
  • ฟังก์ชันกำลังในการสร้าง, สแควร์รูทหรือ xroot ใด ๆ ถูกห้าม
  • โปรแกรมของคุณจะต้องไม่รับอินพุตใด ๆ มันจะต้องมีทั้งหมดในตัวเอง

คะแนนของคุณคือขนาดของโปรแกรมเริ่มต้นของคุณใน UTF-8 ไบต์ คะแนนต่ำสุดชนะ


เราจำเป็นต้องกำหนดฟังก์ชั่นหรือเราจะทำให้การเขียนง่ายขึ้นได้x = x-(x*x-2)/(2*x)ไหม?
Kyle Kanos

การทำให้เข้าใจง่ายนั้นดูสมเหตุสมผลสำหรับฉัน ตราบใดที่มันทำการคำนวณโดยใช้วิธีของนิวตัน
lochok

โปรแกรมแสดงผลลัพธ์โดยประมาณหรือเพียงแค่ซอร์สโค้ดหรือไม่ สามารถใช้เป็นอินพุตของโซลูชันก่อนหน้าได้หรือไม่
Emily

มันจะต้องส่งออกประมาณ (ความเห็น) ในบรรทัดแรกด้วยรหัสที่มาสำหรับการทำซ้ำต่อไป การประมาณอาจนำหน้าโดย shebang หากภาษานั้นต้องการ โปรแกรม (หรือโปรแกรมที่สร้าง) ต้องไม่ยอมรับอินพุตใด ๆ
224 lochok

คำตอบ:


19

เสียงกระเพื่อมสามัญ, 223 95 68 66

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

ตอนนี้ฉันอ่านคำแถลงปัญหาอย่างรอบคอบมากขึ้น (ขอบคุณพรีโม่ !) ฉันสังเกตเห็นว่าบรรทัดแรกต้องเป็นผลลัพธ์ของการคำนวณไม่ใช่ว่าจะต้องมีผลลัพธ์ ดังนั้นฉันคิดว่าความพยายามก่อนหน้านี้ของฉันไม่ได้ทำตามกฎ อันนี้ควร

ตัวอย่างการใช้งาน (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)
$

ฉันได้ทำการทดสอบกับ CCL เป็นส่วนใหญ่ แต่ก็ทำงานได้ใกล้เคียงกับทั้ง SBCL และ CLISP
jlahd

1
นี่เป็นมากกว่าที่ฉันคาดไว้ +1
โม่

17

Python 60 ไบต์

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

ฉันทำให้สูตรง่ายขึ้นเล็กน้อยโดยใช้การแทนที่ต่อไปนี้:

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

ฉันหวังว่านั่นไม่ใช่ปัญหา

โปรแกรมดำเนินการในลักษณะดังต่อไปนี้:

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

เป็นต้น


ฉันไม่รู้ว่านี่ถูกกฎหมายหรือไม่ แต่คุณสามารถย่อรหัสเริ่มต้นของคุณเป็นg="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)@ 50 chars ได้
cjfaure

@Trimsty ฉันคิดว่ามันเป็นปัญหาเล็กน้อยที่ 1) มันไม่ได้คำนวณการทำซ้ำครั้งแรกและ 2) บรรทัดแรกไม่มีผลลัพธ์ปัจจุบัน เมื่อฉันเข้าใจคำอธิบายปัญหาแล้วทั้งโปรแกรมดั้งเดิมและรุ่นต่อ ๆ มาควรมีคุณสมบัติตรงตามเกณฑ์เหล่านี้
โม่

13

CJam, 20 ไบต์

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

ลองออนไลน์

เอาท์พุต

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

มันทำงานอย่างไร

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
เป็นเรื่องที่น่าประทับใจมาก +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)

นี่เป็นเช่นเดียวกับข้างต้นสำหรับเบราว์เซอร์รุ่นเก่า


1
บางครั้งฉันก็ประหลาดใจว่าจาวาสคริปต์ง่ายๆสามารถทำสิ่งต่าง ๆ ได้อย่างไร +1
seequ

นี้ดูเหมือนว่าจะขาดการเรียงลำดับของการส่งออกใด ๆ ( print, putstr, console.logฯลฯ )
โม่

@primo - เมื่อเรียกใช้ JavaScript ในคอนโซลค่าที่ส่งคืนจะถูกพิมพ์โดยอัตโนมัติ
Derek 朕會功夫

@Derek 朕會功夫มีภาษามากมายที่สามารถรันเป็น REPL ได้ - นี่เป็นนิพจน์ไม่ใช่โปรแกรมที่สมบูรณ์ ดู: มาตรฐาน“ช่องโหว่” ซึ่งจะไม่ตลกอีกต่อไป
primo

1
@Derek 朕會功夫คำอธิบายปัญหาถามหาโปรแกรมโดยเฉพาะ - ในหลาย ๆ ที่ โปรแกรมที่ให้มาไม่ทำอะไรเลย พยาน: i.stack.imgur.com/Te7Vf.pngด้านบนคือนิพจน์ที่ประเมินการแสดงออก มันมีข้อดีของมันเอง แต่มันไม่ใช่โปรแกรม
โม่

6

ลัวะ 129

อาจจะนานเกินไป แต่ Lua Quine ดูดได้เนื่องจากซ้อนกัน[[ ]]เป็นคุณลักษณะที่เลิกใช้แล้ว แต่มันทำงานโดยไม่คำนึงถึง:

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)

มันค่อนข้างดีกว่าถ้าคุณเพิ่มบรรทัดใหม่แทน colons:

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 ไบต์

นี่มันช่างน่ากลัวเหมือนฉันกำลังทำ quines (ฉันอาจจะแก้ไขสิ่งนี้เมื่อฉันได้ความคิดที่ดีขึ้น) โฟลทของเจ จำกัด เพียง 5 ตำแหน่งทศนิยม แต่ด้วยการแทนที่บรรทัดแรกด้วยx=:1xมันจะเป็นเศษส่วนด้วยความแม่นยำที่ไม่มีที่สิ้นสุด

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

การทำซ้ำสองสามครั้งแรก:

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

คำอธิบาย

((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
ฉันชอบที่โปรแกรมนี้เรียบง่าย (สำหรับร้ายแรง)
Seequ

ถ้าฉันมีเวลามากขึ้นฉันจะดูว่าฉันสามารถแก้ไขข้างต้นสำหรับ Kona ได้หรือไม่
Kyle Kanos

@ KyleKanos อย่างน้อยตัวเลขการหมุน - เรื่องก็คล้ายกันมากพอ แต่ฉันไม่รู้ Kona โชคดี! :)
seequ

1%x%xเป็นเช่นเดียวกับ แทนการที่คุณสามารถทำได้(x%2)+1%x (%&2+%)x
Conor O'Brien

3

ทับทิม, 65

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

บ่อยครั้งที่สิ่งนี้เกิดขึ้นเกือบจะเป็นพอร์ตตรงของโซลูชัน Python

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.