Квайны — различия между версиями
Xottab (обсуждение | вклад) м (→Интроны) |
Xottab (обсуждение | вклад) |
||
Строка 2: | Строка 2: | ||
|definition='''Квайном''' (англ. ''quine'')<ref name=quineName/> называется программа, которая выводит свой исходный код. При этом, программа не должна использовать внешние данные (например, читать файл со своим исходным кодом). | |definition='''Квайном''' (англ. ''quine'')<ref name=quineName/> называется программа, которая выводит свой исходный код. При этом, программа не должна использовать внешние данные (например, читать файл со своим исходным кодом). | ||
}} | }} | ||
− | |||
− | |||
Квайн состоит из двух сегментов: <b>кода</b> и <b>данных</b>. Данные представляют собой текстовую версию кода, и, как правило, получаются из кода простым добавлением обрамляющих кавычек. Код, в свою очередь, сначала использует данные, чтобы вывести код(содержащийся в них), а затем, просто выводит данные. | Квайн состоит из двух сегментов: <b>кода</b> и <b>данных</b>. Данные представляют собой текстовую версию кода, и, как правило, получаются из кода простым добавлением обрамляющих кавычек. Код, в свою очередь, сначала использует данные, чтобы вывести код(содержащийся в них), а затем, просто выводит данные. | ||
Строка 10: | Строка 8: | ||
==Интроны== | ==Интроны== | ||
{{Определение | {{Определение | ||
− | |definition='''Интроном''' (англ. ''intron'') называется часть сегмента данных, которая не используется для вывода кода, но сохраняющаяся в процессе саморепликации квайна. | + | |definition='''Интроном''' (англ. ''intron'')<ref name=intronName/> называется часть сегмента данных, которая не используется для вывода кода, но сохраняющаяся в процессе саморепликации квайна. |
}} | }} | ||
− | |||
− | |||
==Мульти-квайны== | ==Мульти-квайны== | ||
{{Определение | {{Определение | ||
Строка 19: | Строка 15: | ||
*при обычном запуске она выводит свой исходный код, | *при обычном запуске она выводит свой исходный код, | ||
*при запуске с особым аргументом она выводит исходный код своего "брата" на другом языке программирования. | *при запуске с особым аргументом она выводит исходный код своего "брата" на другом языке программирования. | ||
− | Её брат делает то же самое: выводит свой код при запуске без аргументов и выводит код оригинальной программы при запуске с переданным | + | Её брат делает то же самое: выводит свой код при запуске без аргументов и выводит код оригинальной программы при запуске с переданным специальным аргументом. |
}} | }} | ||
{{Определение | {{Определение | ||
Строка 32: | Строка 28: | ||
|proof= Докажем утверждение для би-квайна, для большего количества языков доказательство будет выглядеть аналогично. | |proof= Докажем утверждение для би-квайна, для большего количества языков доказательство будет выглядеть аналогично. | ||
− | Рассмотрим программу с двумя параметрами на языке <tex>L_1</tex>, которая выводит первый параметр при обычном запуске и второй - при запуске со спец. аргументом. По [ | + | Рассмотрим программу с двумя параметрами на языке <tex>L_1</tex>, которая выводит первый параметр при обычном запуске и второй - при запуске со спец. аргументом. По [[Теорема о рекурсии|теореме о рекурсии]] мы можем зафиксировать первый параметр и сказать, что он будет равен исходному коду нашей программы. Таким образом, мы получим программу с одним параметром, которая выводит свой код при запуске без аргументов и выводит параметр при запуске со спец. аргументом. Проделаем то же самое для программы на языке <tex>L_2</tex>. И наконец, зафиксируем как параметр первой исходный код второй и наоборот. |
}} | }} | ||
===Принцип написания=== | ===Принцип написания=== | ||
Будем следовать доказательству и напишем мульти-квайн для двух языков. Далее покажем, как добавить новый язык. | Будем следовать доказательству и напишем мульти-квайн для двух языков. Далее покажем, как добавить новый язык. | ||
− | + | * напишем для каждого языка "полу-квайн": | |
− | + | <table> | |
− | + | <tr> | |
− | + | <td><center><tex>P_1(p,arg)</tex></center></td> | |
− | + | <td><center><tex>P_2(p,arg)</tex></center></td> | |
− | + | </tr> | |
− | + | <tr> | |
− | </ | + | <td><code><font size = "2em"> |
− | + | if (arg == "print second!") | |
− | + | print(p) | |
− | + | else | |
− | + | print(getSrc()) | |
− | + | </font></code></td> | |
− | + | <td><code><font size = "2em"> | |
− | + | if (arg == "print first!") | |
− | + | print(p) | |
− | </ | + | else |
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | </tr> | ||
+ | </table> | ||
+ | * добавим код каждой из программ интроном в код другой | ||
+ | * модифицируем каждую из программ, чтобы вместо <tex>p</tex> она выводила интрон: | ||
+ | <table> | ||
+ | <tr> | ||
+ | <td><center><tex>P_1(arg)</tex></center></td> | ||
+ | <td><center><tex>P_2(arg)</tex></center></td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td><code><font size = "2em"> | ||
+ | if (arg == "print second!") | ||
+ | print(p2_intron) | ||
+ | else | ||
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | <td><code><font size = "2em"> | ||
+ | if (arg == "print first!") | ||
+ | print(p1_intron) | ||
+ | else | ||
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | </tr> | ||
+ | </table> | ||
Теперь добавим третий язык: | Теперь добавим третий язык: | ||
− | + | * напишем для него "полу-квайн", но уже с двумя параметрами и тремя возможными выводами: | |
− | + | <code><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></code> | |
− | + | * добавим третье условие в два уже существующих квайна: | |
− | + | <table> | |
− | + | <tr> | |
− | + | <td><center><tex>P_1(p,arg)</tex></center></td> | |
− | + | <td><center><tex>P_2(p,arg)</tex></center></td> | |
− | + | </tr> | |
− | + | <tr> | |
− | </ | + | <td><code><font size = "2em"> |
− | + | if (arg == "print second!") | |
− | + | print(p2_intron) | |
− | + | elseif (arg == "print third!") | |
− | + | print(p) | |
− | + | else | |
− | + | print(getSrc()) | |
− | + | </font></code></td> | |
− | + | <td><code><font size = "2em"> | |
− | + | if (arg == "print first!") | |
− | </ | + | print(p1_intron) |
+ | elseif (arg == "print third!") | ||
+ | print(p) | ||
+ | else | ||
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | </tr> | ||
+ | </table> | ||
+ | * подставим код первых двух интронами в третью, а код третьей - вторым интроном в каждую из двух первых: | ||
+ | <table> | ||
+ | <tr> | ||
+ | <td><center><tex>P_1(arg)</tex></center></td> | ||
+ | <td><center><tex>P_2(arg)</tex></center></td> | ||
+ | <td><center><tex>P_3(arg)</tex></center></td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td><code><font size = "2em"> | ||
+ | if (arg == "print second!") | ||
+ | print(p2_intron) | ||
+ | elseif (arg == "print third!") | ||
+ | print(p3_intron) | ||
+ | else | ||
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | <td><code><font size = "2em"> | ||
+ | if (arg == "print first!") | ||
+ | print(p1_intron) | ||
+ | elseif (arg == "print third!") | ||
+ | print(p3_intron) | ||
+ | else | ||
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | <td><code><font size = "2em"> | ||
+ | if (arg == "print first!") | ||
+ | print(p1_intron) | ||
+ | elseif (arg == "print second!") | ||
+ | print(p2_intron) | ||
+ | else | ||
+ | print(getSrc()) | ||
+ | </font></code></td> | ||
+ | </tr> | ||
+ | </table> | ||
== Примечания == | == Примечания == | ||
<references> | <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=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> | </references> | ||
== Источники информации == | == Источники информации == | ||
− | * [http://www.madore.org/~david/computers/quine.html Madore.org | + | * [http://www.madore.org/~david/computers/quine.html Madore.org — Quines (self-replicating programs)] |
− | * [http://habrahabr.ru/post/186782/ Хабрахабр | + | * [http://habrahabr.ru/post/186782/ Хабрахабр — Эстафета из 50 квайнов] |
− | * [http://habrahabr.ru/post/188378/ Хабрахабр | + | * [http://habrahabr.ru/post/188378/ Хабрахабр — Мультиязыковые квайны] |
− | * [http://habrahabr.ru/post/128191/ Хабрахабр | + | * [http://habrahabr.ru/post/128191/ Хабрахабр — Как писать квайны] |
[[Категория: Теория формальных языков]] | [[Категория: Теория формальных языков]] | ||
[[Категория: Теория вычислимости]] | [[Категория: Теория вычислимости]] |
Версия 16:09, 6 января 2015
Определение: |
Квайном (англ. quine)[1] называется программа, которая выводит свой исходный код. При этом, программа не должна использовать внешние данные (например, читать файл со своим исходным кодом). |
Квайн состоит из двух сегментов: кода и данных. Данные представляют собой текстовую версию кода, и, как правило, получаются из кода простым добавлением обрамляющих кавычек. Код, в свою очередь, сначала использует данные, чтобы вывести код(содержащийся в них), а затем, просто выводит данные.
Формально общий принцип написания квайнов содержится в доказательстве теоремы о рекурсии. Далее будет рассмотрено понятие мульти-квайна.
Интроны
Определение: |
Интроном (англ. intron)[2] называется часть сегмента данных, которая не используется для вывода кода, но сохраняющаяся в процессе саморепликации квайна. |
Мульти-квайны
Определение: |
Би-квайном (англ. bi-quine) называется программа, которая делает одно из двух:
|
Определение: |
-квайном (англ. -quine) называется программа, способная вывести исходный код программ на других языках программирования в зависимости от переданного ей аргумента, а так же свой исходный код при вызове без аргументов. |
Заметим, что требование, чтобы программы были на разных языках программирования важно, т.к. иначе все программы смогут иметь один и тот же код.
Теорема (о существовании мульти-квайнов): |
На любом языке программирования можно написать мульти-квайн |
Доказательство: |
Докажем утверждение для би-квайна, для большего количества языков доказательство будет выглядеть аналогично. Рассмотрим программу с двумя параметрами на языке , которая выводит первый параметр при обычном запуске и второй - при запуске со спец. аргументом. По теореме о рекурсии мы можем зафиксировать первый параметр и сказать, что он будет равен исходному коду нашей программы. Таким образом, мы получим программу с одним параметром, которая выводит свой код при запуске без аргументов и выводит параметр при запуске со спец. аргументом. Проделаем то же самое для программы на языке . И наконец, зафиксируем как параметр первой исходный код второй и наоборот. |
Принцип написания
Будем следовать доказательству и напишем мульти-квайн для двух языков. Далее покажем, как добавить новый язык.
- напишем для каждого языка "полу-квайн":
|
|
- добавим код каждой из программ интроном в код другой
- модифицируем каждую из программ, чтобы вместо она выводила интрон:
|
|
Теперь добавим третий язык:
- напишем для него "полу-квайн", но уже с двумя параметрами и тремя возможными выводами:
:
if (arg == "print first!")
print(p1)
elseif (arg == "print second!")
print(p2)
else
print(getSrc())
- добавим третье условие в два уже существующих квайна:
|
|
- подставим код первых двух интронами в третью, а код третьей - вторым интроном в каждую из двух первых:
|
|
|
Примечания
- ↑ Название "квайн" было предложено Дугласом Хофштадтером, в его известной книге "Гёдель, Эшер, Бах: Эта бесконечная гирлянда" в честь американского логика и философа Уилларда Ван Ормана Квайна, который углублённо изучал явление косвенного самоупоминания.
- ↑ Название пришло из биологии, где интронами называются части ДНК, не участвующие в синтезе протеинов.