牛顿法递归法


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]移到更接近于2的平方根。所以-

  • 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 2014年

对我来说,这种简化是有效的。只要它使用牛顿法执行计算
lochok

程序是输出近似值还是仅输出源代码?可以将先前的解决方案作为输入吗?
艾米丽

它必须在第一行输出近似值(带注释),并带有下一次迭代的源代码。如果语言需要,可以在逼近之前加上shebang。程序(也不生成程序)不得接受任何输入。
lochok 2014年

Answers:


19

普通Lisp,223 95 68 66

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

现在,我更加仔细地阅读了问题说明(感谢primo!),我注意到第一行必须计算的结果,而不是必须包含结果。因此,我认为我以前的尝试并没有完全遵循规则。这个应该。

用法示例(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 2014年

1
这更像我期望的那样。+1
primo

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个字符。
cjfaure

@Trimsty我认为1)它实际上没有计算第一次迭代,以及2)第一行不包含当前结果,这有点麻烦。据我了解问题描述,原始程序和后代程序都应满足这些条件。
2014年

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
凯尔·卡诺斯

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
有时我只是惊讶于简单的javascript可以完成任务。+1
seequ 2014年

这似乎缺乏任何形式输出(printputstrconsole.log等)。
2014年

@primo-在控制台中运行JavaScript时,将自动打印返回的值。
德里克·朕会功夫2014年

@Derek朕会功夫许多语言都可以作为REPL运行-这是一个表达式,而不是一个完整的程序。请参阅:不再有趣的标准“漏洞”
2014年

1
@Derek朕会功夫问题描述专门在多个地方要求程序。提供的程序不执行任何操作。见证人:i.stack.imgur.com/Te7Vf.png上面是一个表达式,其结果为一个表达式。它有自己的优点,但不是程序。
2014年

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)

看看是否添加换行符而不是冒号会更好一些:

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字节

这和我制作藜一样可怕(当我有了更好的主意时,我可能会修改它)。J的浮点数限制为小数点后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 2014年

如果有更多时间,我将看看是否可以为Kona修改以上内容。
Kyle Kanos 2014年

@KyleKanos至少digit-rotation-thingy足够相似,但我不知道Kona。祝好运!:)
seequ 2014年

1%x与相同%x。相反(x%2)+1%x,您可以这样做(%&2+%)x
科纳·奥布莱恩

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

经常发生的情况,这几乎是Python解决方案的直接体现。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.