재귀 Quines에 의한 뉴턴 방법


32

당신의 임무는 약간의 비틀림과 함께 뉴턴의 방법을 사용하여 2의 제곱근을 계산하는 것입니다. 귀하의 프로그램은 Newton의 방법을 사용하여 반복을 계산하고 다음 반복에 대한 소스 코드를 출력합니다 (동일하게 수행 할 수 있어야 함).

뉴턴의 방법은 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

그 단순화는 나에게 유효 해 보인다. 그것이 뉴턴의 방법을 사용하여 계산을 수행하는 한
lochok

프로그램이 근사값을 출력합니까 아니면 소스 코드 만 출력합니까? 이전 솔루션의 입력으로 사용할 수 있습니까?
Emily

다음 반복을위한 소스 코드와 함께 첫 번째 행에 근사값 (주석)을 출력해야합니다. 언어에 필요한 경우 근사값 앞에 shebang이 올 수 있습니다. 프로그램 (또는 프로그램이 생성하는 프로그램)은 입력을 허용하지 않아야합니다.
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
primo 2016 년

17

파이썬 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) 첫 번째 줄에 현재 결과가 포함되어 있지 않다는 것이 약간 문제가 있다고 생각합니다. 문제 설명을 이해하면 원래 프로그램과 그 이후 세대 모두이 기준을 충족해야합니다.
primo

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 2018 년

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)

자바 스크립트, 51

(function f(x){return "("+f+")("+(x/2+1/x)+")"})(1)

이전 브라우저의 경우 위와 동일합니다.


1
때로는 간단한 자바 스크립트로 어떻게 만들 수 있는지 놀랐습니다. +1
seequ

이것은 (출력의 어떤 종류이 부족하다고 생각 print, putstr, console.log, 등).
primo

@primo-JavaScript가 콘솔에서 실행될 때 반환 된 값이 자동으로 인쇄됩니다.
Derek 朕 會 功夫

@Derek 朕 會 功夫 많은 언어를 REPL로 실행할 수 있습니다. 이것은 완전한 프로그램이 아니라 표현입니다. 더 이상 재미없는 표준“허점”을 참조하십시오 .
primo

1
@Derek 朕 會 功夫 문제 설명은 구체적으로 여러 곳에서 프로그램을 요구합니다. 제공된 프로그램은 아무 것도 수행하지 않습니다. 증인 : i.stack.imgur.com/Te7Vf.png 위의 표현은 표현식으로 평가되는 표현식입니다. 자체 장점이 있지만 프로그램은 아닙니다.
primo

6

루아 129

아마도 너무 길지만 루아 퀘인은 중첩 된 [[ ]]기능이 더 이상 사용되지 않기 때문에 짜증납니다 . 그러나 그것은 관계없이 작동합니다 :

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 바이트

이것은 quines를 만드는 것만 큼 끔찍합니다 (더 나은 아이디어를 얻으면 아마 이것을 수정할 것입니다). J의 float는 소수점 이하 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.
코너 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

너무 자주 발생하는 것처럼 이것은 거의 파이썬 솔루션의 직선 포트입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.