Метод Ньютона по рекурсивным квинам


32

Ваша задача - вычислить квадратный корень из 2, используя метод Ньютона - с легким поворотом. Ваша программа должна рассчитать итерацию, используя метод Ньютона, и вывести исходный код для следующей итерации (которая должна быть в состоянии сделать то же самое).

Метод Ньютона довольно исчерпывающе описан в Википедии

Чтобы вычислить квадратный корень 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]и удовлетворять тем же критериям этого вопроса.
  • В первой строке исходного кода должен быть результат вычисления, правильно закомментированный. Если источнику требуется что-то конкретное (например, шебанг) ​​в первой строке, результат может быть помещен во вторую строку.

Обратите внимание, что

  • Ваша программа должна использовать первоначальное предположение x[0] = 1
  • В стандартных лазейки применяются
  • Любые встроенные функции power, square root или xroot запрещены
  • Ваша программа не должна принимать какие-либо данные. Он должен быть полностью автономным.

Ваша оценка - это размер вашей начальной программы в байтах UTF-8. Самый низкий балл побеждает.


Нужно ли нам определять функции, или мы можем упростить, написав x = x-(x*x-2)/(2*x)?
Кайл Канос

Это упрощение выглядит актуально для меня. Пока он выполняет вычисления с использованием метода Ньютона
lochok

Программа выводит приближение или только исходный код? Может ли он принять в качестве входных данных предыдущее решение?
Эмили

Он должен вывести аппроксимацию (закомментированную) в первой строке с исходным кодом для следующей итерации. Приближению может предшествовать шебанг, если этого требует язык. Программа (и программа, которую она производит) не должна принимать никаких входных данных.
Лочок

Ответы:


19

Common 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

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) первая строка не содержит текущий результат. Как я понимаю описание проблемы, эти критерии должны удовлетворять как исходная программа, так и последующие поколения.
Примо

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

Это , кажется, отсутствует какой - либо продукции ( print, putstr, console.logи т.д.).
Примо

@primo - Когда JavaScript запускается в консоли, возвращаемое значение печатается автоматически.
Дерек 朕 會 功夫

@Derek 朕 會 功夫 Очень многие языки могут быть запущены как REPL - это выражение, а не полная программа. Смотрите: стандартные «лазейки», которые больше не смешны .
Примо

1
@Derek 朕 會 功夫 Описание проблемы специально запрашивает программу - в нескольких местах. Поставленная программа ничего не делает. Witness: 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)

Немного приятнее посмотреть, добавляете ли вы новые строки вместо двоеточий:

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

Если у меня будет больше времени, я посмотрю, смогу ли я изменить вышеперечисленное для Kona.
Кайл Канос

@KyleKanos По крайней мере, цифра-вращение-вещь была достаточно похожа, но я не знаю, Кона. Удачи! :)
seequ

1%xтак же, как %x. Вместо (x%2)+1%xвы можете сделать (%&2+%)x.
Конор О'Брайен,

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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.