Изменения

Перейти к: навигация, поиск

Квайны

5383 байта добавлено, 19:38, 4 сентября 2022
м
rollbackEdits.php mass rollback
{{В разработке}}
{{Определение
|definition='''Квайном''' (англ. '''куайном, quine''') <ref name=quineName/> называется программа, которая выводит свой исходный код. При этом, программа не должна использовать внешние данные (например, читать файл со своим исходным кодом).
}}
Стоит отметить, что программы, использующие для чтения своего кода файловую систему, квайнами не считаются. Например, программа на BASIC вида <font size ==Происхождение названия==Название "квайн2em" было предложено [http:> 10 LIST</font>выводит на экран свой исходный код, поскольку команда <tex>\mathtt{LIST}</rutex> просит среду исполнения вывести в консоль текущую программу (эта функция была необходима для программистов, так как код программы зачастую не мог поместиться на консоль 80x25 символов).wikipedia Квайн состоит из двух сегментов: кода и данных.org/wiki/ХофштадтерДанные представляют собой текстовую версию кода, и, как правило,_Дуглас Дугласом Хофштадтером]получаются из кода простым добавлением обрамляющих кавычек. Код, в его известной книге "Гёдельсвою очередь, сначала использует данные, чтобы вывести код, Эшерсодержащийся в них, Бах: Эта бесконечная гирлянда" а затем просто выводит данные. Формально общий принцип написания квайнов содержится в честь американского логика и философа доказательстве [[http://ruТеорема о рекурсии|теоремы о рекурсии]]. Далее будет рассмотрено понятие мультиквайна.wikipedia ==Мультиквайны=====Связанные определения==={{Определение|definition='''Интроном''' (англ.org/wiki''intron'')<ref name=intronName/Куайн> называется часть сегмента данных,_Уиллард_Ван_Орман Уилларда Ван Ормана Квайна]которая не используется для вывода кода, который углублённо изучал явление [http://enно сохраняется в процессе саморепликации квайна.wikipedia}}{{Определение|definition='''Биквайном''' (англ.org/wiki/Indirect_self-reference косвенного самоупоминания]. в частности''biquine'') называется программа, это явление можно проиллюстрировать следующим парадоксальным утверждениемкоторая делает одно из двух:*при обычном запуске она выводит свой исходный код, известном как парадокс Квайна*при запуске с особым аргументом она выводит исходный код своего "брата" на другом языке программирования.Её "брат" делает то же самое: выводит свой код при запуске без аргументов и выводит код оригинальной программы при запуске с переданным специальным аргументом.}}{{ТеоремаОпределение|aboutdefinition=парадокс Квайна|statement="Становится ложным'''<tex>R</tex>-квайном''' (англ. <tex>R</tex>-''quine'') называется программа, когда добавляется к собственной цитате" становится ложнымспособная вывести исходный код <tex>R-1</tex> программ на других языках программирования в зависимости от переданного ей аргумента, когда добавляется к собственной цитатеа также свой исходный код при вызове без аргументов.
}}
==Доказательство существования==Заметим, что требование, чтобы программы были на разных языках программирования, важно, иначе все программы смогут иметь один и тот же код.
{{
Теорема
|about=о существовании квайновмультиквайнов|statement= На любом языке программирования можно написать квайнмультиквайн.|proof= Докажем утверждение для биквайна. Для большего количества языков доказательство будет выглядеть аналогично. Рассмотрим функцию программу с двумя параметрами на языке <tex>h(t)L_1</tex>, которая по данной программе <tex>t</tex> печатает её исходный кодвыводит первый параметр при обычном запуске и второй {{---}} при запуске со спец. Очевидно, она вычислимааргументом. По [http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8#.D0.A2.D0.B5.D0.BE.D1.80.D0.B5.D0.BC.D0.B0_.D0.BE_.D0.BD.D0.B5.D0.BF.D0.BE.D0.B4.D0.B2.D0.B8.D0.B6.D0.BD.D0.BE.D0.B9_.D1.82.D0.BE.D1.87.D0.BA.D0.B5 [Теорема о рекурсии|теореме о неподвижной точкерекурсии]]существует такая программа <tex>n</tex>мы можем зафиксировать первый параметр и сказать, что <tex>h(n)</tex> и <tex>n</tex> ведут себя одинаково, то есть печатают свой кодон будет равен исходному коду нашей программы. Таким образом, <tex>n</tex> печатает мы получим программу с одним параметром, которая выводит свой код при запуске без аргументов и выводит параметр при запуске со спец. аргументом. Проделаем то же самое для программы на языке <tex>nL_2</tex>. И, наконец, т.е. является квайномзафиксируем как параметр первой программы исходный код второй и наоборот.
}}
==Общий принцип написания квайнов==
Квайн состоит из двух частей: <b>кода</b> и <b>данных</b>. Данные представляют собой текстовую версию кода, и, как правило, получаются из кода простым добавлением обрамляющих кавычек. Код, в свою очередь, сначала использует данные, чтобы вывести код(содержащийся в них), а затем, просто выводит данные.
Чтобы написать простой квайн на C, мы положим в данные текстовое представление кода и при выводе данных будем экранировать знаки табуляции и переносов:
<nowiki>const char data [] =
"#include <stdio.h>\n\nint\nmain (void)\n{\n unsigned int i;\n\n p"
"rintf (\"const char data [] =\");\n for ( i=0 ; data[i] ; i++ "
")\n {\n if ( i%60 == 0 )\n\tprintf (\"\\n\\\"\");\n switc"
"h ( data[i] )\n\t{\n\tcase '\\\\':\n\tcase '\"':\n\t printf (\"\\\\%c\", d"
"ata[i]);\n\t break;\n\tcase '\\n':\n\t printf (\"\\\\n\");\n\t break;\n"
"\tcase '\\t':\n\t printf (\"\\\\t\");\n\t break;\n\tdefault:\n\t printf"
" (\"%c\", data[i]);\n\t}\n if ( i%60 == 59 || !data[i+1] )\n\t"
"printf (\"\\\"\");\n }\n printf (\";\\n\\n\");\n for ( i=0 ; data["
"i] ; i++ )\n putchar (data[i]);\n return 0;\n}\n";
#include ===Принцип написания===Будем следовать доказательству и напишем мультиквайн для двух языков. Далее покажем, как добавить новый язык.* напишем для каждого языка "полуквайн":<table><tr><td><font size = "2em"> <tex>P_1(p,arg)</tex>: '''if''' (arg == "print second!") '''print'''(p) '''else''' '''print'''(getSrc()) </font></td><td><font size = "2em"> <tex>P_2(p,arg)</tex>: '''if''' (arg == "print first!") '''print'''(p) '''else''' '''print'''(getSrc()) </font></td></tr></table>* подставим код второй программы в первую:<font size = "2em"> <stdiotex>P_1(p,arg)</tex>: '''if''' (arg == "print second!") '''print'''(<tex>P_2</tex>(p, arg).hgetSrc()) '''else''' '''print'''(getSrc()) </font>* применим [[Теорема о рекурсии|теорему о рекурсии]] и заменим параметр на исходный код программы: <font size = "2em"> <tex>P_1(arg)</tex>: '''if''' (arg == "print second!") '''print'''(<tex>P_2</tex>(getSrc(), arg).getSrc()) '''else''' '''print'''(getSrc()) </font>Вторая программа может быть получена запуском первой с нужным аргументом.
intТеперь добавим третий язык:main * напишем для него "полуквайн", но уже с двумя параметрами и тремя возможными выводами:<font size = "2em"> <tex>P_3(p1,p2,arg)</tex>: '''if''' (arg == "print first!") '''print'''(p1) '''elseif''' (arg == "print second!") '''print'''(p2) '''else''' '''print'''(getSrc()) </font>* добавим параметр в два уже существующих квайна: <table><tr><td><font size = "2em"> <tex>P_1(p,arg)</tex>: '''if''' (arg == "print second!") '''print'''(<tex>P_2</tex>(p, getSrc(), arg).getSrc()) '''elseif''' (arg == "print third!") '''print'''(voidp){ '''else''' '''print'''(getSrc()) </font></td><td><font size = "2em"> <tex>P_2(p,arg)</tex>: '''if''' (arg == "print first!") '''print'''(<tex>P_1</tex>(p, getSrc(), arg).getSrc()) '''elseif''' (arg == "print third!") '''print'''(p) '''else''' '''print'''(getSrc()) </font></td></tr> unsigned int i;</table>
printf (* подставим код первых двух в третью:<font size = "const char data [] =2em");> for <tex>P_3( i=0 ; data[i] ; i++ p1,p2,arg)</tex>: { '''if ''' ( i%60 arg == 0 "print first!") printf '''print'''("\n\""<tex>P_1</tex>(p1, arg); switch .getSrc( data[i] )) { case '''\\elseif': case '"': printf (arg == "\\%cprint second!", data[i]); break; case '''print''\n': printf ("\\n"<tex>P_2</tex>(p2, arg).getSrc()); break; '''else''' case '''print''\t': printf ("\\t"getSrc()); break;</font>  default* применим [[Теорема о рекурсии|теорему о рекурсии]] и заменим оба параметра на исходный код программы: printf (<font size = "%c2em", data[i]> <tex>P_3(arg);</tex>: } '''if ''' ( i%60 arg == 59 || "print first!data[i+1] ") printf '''print'''(<tex>P_1</tex>(getSrc("\""); } printf , arg).getSrc(";\n\n");) for '''elseif''' ( iarg ==0 ; data[i] ; i++ "print second!") putchar '''print'''(data[i]); return 0;}<tex>P_2</nowikitex>(getSrc(), arg).getSrc())==Связанные определения== '''else'''===Интроны==={{Определение|definition= '''Интрономprint''' (introngetSrc()) называется часть данных, которая не используется для вывода кода, но сохраняющаяся в процессе саморепликации квайна.}}</font>===Мульти-квайны=====Bootstrapping==Две оставшиеся программы будут выглядеть аналогично и смогут быть получены путём запуска третьей с каждым из возможных аргументов.
== Примечания ==
<references>
<ref name=quineName>Название "квайн" было предложено [http://ru.wikipedia.org/wiki/Хофштадтер,_Дуглас Дугласом Хофштадтером], в его известной книге "Гёдель, Эшер, Бах: Эта бесконечная гирлянда" в честь американского логика и философа [http://ru.wikipedia.org/wiki/Куайн,_Уиллард_Ван_Орман Уилларда Ван Ормана Квайна], который углублённо изучал явление [http://en.wikipedia.org/wiki/Indirect_self-reference косвенного самоупоминания].</ref>
<ref name=intronName>Название пришло из биологии, где интронами называются части ДНК, не участвующие в синтезе протеинов.</ref>
</references>
== Источники информации ==
* [http://www.madore.org/~david/computers/quine.html Madore.org &mdash; Quines (self-replicating programs)]
* [http://habrahabr.ru/post/186782/ Хабрахабр &mdash; Эстафета из 50 квайнов]
* [http://habrahabr.ru/post/188378/ Хабрахабр &mdash; Мультиязыковые квайны]
* [http://habrahabr.ru/post/128191/ Хабрахабр &mdash; Как писать квайны]
* [http://en.wikipedia.org/wiki/Quine_(computing)#Multiquines Wikipedia &mdash; Multi-quines]
== Ссылки ==[[Категория: Теория формальных языков]]* [http[Категория://www.madore.org/~david/computers/quine.html Quines (self-replicating programs)Теория вычислимости]]
1632
правки

Навигация