Квайны — различия между версиями
Xottab (обсуждение | вклад) (→Происхождение названия) |
|||
Строка 18: | Строка 18: | ||
|proof= Рассмотрим функцию <tex>h(t)</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>n</tex>, т.е. является квайном. | |proof= Рассмотрим функцию <tex>h(t)</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>n</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 <stdio.h> | ||
+ | |||
+ | int | ||
+ | main (void) | ||
+ | { | ||
+ | unsigned int i; | ||
+ | |||
+ | printf ("const char data [] ="); | ||
+ | for ( i=0 ; data[i] ; i++ ) | ||
+ | { | ||
+ | if ( i%60 == 0 ) | ||
+ | printf ("\n\""); | ||
+ | switch ( data[i] ) | ||
+ | { | ||
+ | case '\\': | ||
+ | case '"': | ||
+ | printf ("\\%c", data[i]); | ||
+ | break; | ||
+ | case '\n': | ||
+ | printf ("\\n"); | ||
+ | break; | ||
+ | case '\t': | ||
+ | printf ("\\t"); | ||
+ | break; | ||
+ | default: | ||
+ | printf ("%c", data[i]); | ||
+ | } | ||
+ | if ( i%60 == 59 || !data[i+1] ) | ||
+ | printf ("\""); | ||
+ | } | ||
+ | printf (";\n\n"); | ||
+ | for ( i=0 ; data[i] ; i++ ) | ||
+ | putchar (data[i]); | ||
+ | return 0; | ||
+ | }</nowiki> | ||
+ | ==Связанные определения== | ||
+ | ===Интроны=== | ||
+ | {{Определение | ||
+ | |definition='''Интроном''' (intron) называется часть данных, которая не используется для вывода кода, но сохраняющаяся в процессе саморепликации квайна. | ||
+ | }} | ||
+ | ===Мульти-квайны=== | ||
+ | ==Bootstrapping== | ||
+ | |||
+ | |||
== Ссылки == | == Ссылки == | ||
* [http://www.madore.org/~david/computers/quine.html Quines (self-replicating programs)] | * [http://www.madore.org/~david/computers/quine.html Quines (self-replicating programs)] |
Версия 18:53, 3 января 2015
Определение: |
Квайном (куайном, quine) называется программа, которая выводит свой исходный код. При этом, программа не должна использовать внешние данные (например, читать файл со своим исходным кодом). |
Содержание
Происхождение названия
Название "квайн" было предложено Дугласом Хофштадтером, в его известной книге "Гёдель, Эшер, Бах: Эта бесконечная гирлянда" в честь американского логика и философа Уилларда Ван Ормана Квайна, который углублённо изучал явление косвенного самоупоминания. в частности, это явление можно проиллюстрировать следующим парадоксальным утверждением, известном как парадокс Квайна:
Теорема (парадокс Квайна): |
"Становится ложным, когда добавляется к собственной цитате" становится ложным, когда добавляется к собственной цитате. |
Доказательство существования
Теорема (о существовании квайнов): |
На любом языке программирования можно написать квайн |
Доказательство: |
Рассмотрим функцию теореме о неподвижной точкесуществует такая программа , что и ведут себя одинаково, то есть печатают свой код. Таким образом, печатает код , т.е. является квайном. | , которая по данной программе печатает её исходный код. Очевидно, она вычислима. По
Общий принцип написания квайнов
Квайн состоит из двух частей: кода и данных. Данные представляют собой текстовую версию кода, и, как правило, получаются из кода простым добавлением обрамляющих кавычек. Код, в свою очередь, сначала использует данные, чтобы вывести код(содержащийся в них), а затем, просто выводит данные. Чтобы написать простой квайн на C, мы положим в данные текстовое представление кода и при выводе данных будем экранировать знаки табуляции и переносов:
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 <stdio.h> int main (void) { unsigned int i; printf ("const char data [] ="); for ( i=0 ; data[i] ; i++ ) { if ( i%60 == 0 ) printf ("\n\""); switch ( data[i] ) { case '\\': case '"': printf ("\\%c", data[i]); break; case '\n': printf ("\\n"); break; case '\t': printf ("\\t"); break; default: printf ("%c", data[i]); } if ( i%60 == 59 || !data[i+1] ) printf ("\""); } printf (";\n\n"); for ( i=0 ; data[i] ; i++ ) putchar (data[i]); return 0; }
Связанные определения
Интроны
Определение: |
Интроном (intron) называется часть данных, которая не используется для вывода кода, но сохраняющаяся в процессе саморепликации квайна. |