Phương pháp Newton bằng phương pháp đệ quy


32

Nhiệm vụ của bạn là tính căn bậc hai của 2 bằng Phương pháp Newton - với một chút thay đổi. Chương trình của bạn là tính toán một lần lặp bằng Phương pháp của Newton và xuất mã nguồn cho lần lặp sau (phải có khả năng thực hiện tương tự).

Phương pháp của Newton được mô tả khá kỹ lưỡng trên Wikipedia

Để tính căn bậc 2 bằng phương pháp Newton, bạn:

  • Định nghĩa f(x) = x^2 - 2
  • Định nghĩa f'(x) = 2x
  • Xác định x[0](dự đoán ban đầu)= 1
  • Định nghĩa x[n+1] = x[n] - (f[n] / f'[n])

Mỗi lần lặp sẽ di chuyển x [n] gần hơn với căn bậc hai của hai. Vì thế -

  • 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
  • và v.v.

Chương trình của bạn sẽ:

  • Tính toán x[n]đâu nlà số lần chương trình đã được chạy
  • Xuất mã nguồn cho một chương trình hợp lệ trong cùng một ngôn ngữ phải tính toán x[n+1]và đáp ứng cùng tiêu chí của câu hỏi này.
  • Dòng đầu tiên của mã nguồn phải là kết quả tính toán, được nhận xét đúng. Nếu nguồn yêu cầu một cái gì đó cụ thể (chẳng hạn như một shebang) trên dòng đầu tiên, kết quả có thể được đặt trên dòng thứ hai.

Lưu ý rằng

  • Chương trình của bạn phải sử dụng dự đoán ban đầu về x[0] = 1
  • Các lỗ hổng tiêu chuẩn được áp dụng
  • Bất kỳ chức năng xây dựng, căn bậc hai hoặc hàm xroot đều bị cấm
  • Chương trình của bạn không được chấp nhận bất kỳ đầu vào nào. Nó phải hoàn toàn khép kín.

Điểm của bạn là kích thước của chương trình ban đầu của bạn theo byte UTF-8. Điểm thấp nhất sẽ thắng.


Chúng ta phải xác định các chức năng, hoặc chúng ta có thể đơn giản hóa bằng cách viết x = x-(x*x-2)/(2*x)?
Kyle Kanos

Sự đơn giản hóa đó có vẻ hợp lệ với tôi. Miễn là nó thực hiện phép tính bằng Phương pháp của Newton
lochok

Chương trình có xuất ra xấp xỉ hay chỉ là mã nguồn? Nó có thể làm đầu vào của nó là giải pháp trước đây?
Emily

Nó phải xuất ra xấp xỉ (nhận xét) trên dòng đầu tiên, với mã nguồn cho lần lặp tiếp theo. Phép tính gần đúng có thể được đi trước bởi một shebang nếu ngôn ngữ yêu cầu. Chương trình (cũng không phải chương trình mà nó tạo ra) không được chấp nhận bất kỳ đầu vào nào.
lochok

Câu trả lời:


19

Lisp thường gặp, 223 95 68 66

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

Bây giờ tôi đã đọc báo cáo vấn đề cẩn thận hơn (cảm ơn, primo !) Tôi nhận thấy rằng dòng đầu tiên phải kết quả của tính toán, không phải là nó cần phải chứa kết quả. Vì vậy, tôi nghĩ rằng những nỗ lực trước đây của tôi không hoàn toàn tuân theo các quy tắc. Điều này nên.

Ví dụ sử dụng (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)
$

Tôi đã chủ yếu thử nghiệm với CCL, nhưng nó hoạt động tương tự với cả SBCL và CLISP.
jmusd

1
Điều này giống như tôi đã mong đợi. +1
primo

17

Python 60 byte

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

Tôi đã đơn giản hóa công thức một chút, sử dụng các thay thế sau:

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

Tôi hy vọng đó không phải là một vấn đề.

Chương trình tiến hành theo cách sau:

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

v.v.


Tôi không biết điều này có hợp pháp hay không, nhưng bạn có thể rút ngắn mã ban đầu của mình xuống còn g="x=%s;o=%r;print o%%(x/2+1/x,o)";print g%(1.5,g)50 ký tự.
cjfaure

@Trimsty Tôi nghĩ rằng nó hơi có vấn đề khi 1) nó không thực sự tính toán lần lặp đầu tiên và 2) dòng đầu tiên không chứa kết quả hiện tại. Theo tôi hiểu mô tả vấn đề, cả chương trình gốc và thế hệ sau nên đáp ứng các tiêu chí này.
primo

13

CJam, 20 byte

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

Hãy thử trực tuyến.

Đầu ra

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

Làm thế nào nó hoạt động

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
Chà thật ấn tượng. +1
Kyle Kanos

8

Bản thảo 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)

Điều này giống như ở trên, đối với các trình duyệt cũ hơn.


1
Đôi khi tôi chỉ ngạc nhiên khi javascript đơn giản có thể tạo ra mọi thứ. +1
xem

Điều này dường như được thiếu bất kỳ loại đầu ra ( print, putstr, console.log, vv).
primo

@primo - Khi JavaScript được chạy trong bảng điều khiển, giá trị được trả về sẽ tự động được in.
Derek 朕 會

@Derek 會 Rất nhiều ngôn ngữ có thể được chạy dưới dạng REPL - đây là một biểu thức và không phải là một chương trình hoàn chỉnh. Xem: Lỗ hổng tiêu chuẩn của người Viking không còn buồn cười nữa .
primo

1
@Derek 會 Mô tả vấn đề đặc biệt yêu cầu một chương trình - ở một số nơi. Chương trình cung cấp không làm gì cả. Nhân chứng: i.stack.imgur.com/Te7Vf.png Trên đây là một biểu thức đánh giá thành một biểu thức. Nó có giá trị riêng của nó, nhưng nó không phải là một chương trình.
primo

6

Lư 129

Có lẽ cách quá dài, nhưng Lua quine hút vì lồng [[ ]]là một tính năng không dùng nữa. Nhưng nó hoạt động bất kể:

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)

Sẽ tốt hơn một chút để xem nếu bạn thêm dòng mới thay vì dấu hai chấm:

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 byte

Điều này thật kinh khủng như tôi đang thực hiện các nhiệm vụ (tôi có thể sẽ sửa đổi điều này khi tôi có ý tưởng tốt hơn). Phao của J được giới hạn ở 5 vị trí thập phân, nhưng bằng cách thay thế dòng đầu tiên bằng x=:1xnó sẽ là một phần có độ chính xác vô hạn.

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

Vài lần lặp đầu tiên:

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

Giải trình

((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
Tôi thực sự thích cách chương trình này đơn giản (nghiêm túc).
hẹn gặp

Nếu tôi có thêm thời gian, tôi sẽ xem liệu tôi có thể sửa đổi những điều trên cho Kona hay không.
Kyle Kanos

@KyleKanos Ít nhất thì phép quay số là đủ tương tự, nhưng tôi không biết Kona. Chúc may mắn! :)
xem

1%xcũng giống như %x. Thay vì (x%2)+1%x, bạn có thể làm (%&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

Như thường xuyên xảy ra, đây gần như là một cổng thẳng của giải pháp Python.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.