stringtranslate.com

Куайн (вычислительная техника)

Вывод квайна точно такой же, как и его исходный код.

Квайн — это компьютерная программа , которая не принимает никаких входных данных и производит копию своего собственного исходного кода в качестве единственного выхода. Стандартные термины для таких программ в теории вычислимости и литературе по информатике — «самовоспроизводящиеся программы», «самовоспроизводящиеся программы» и «самокопирующиеся программы».

Куайн — это фиксированная точка среды выполнения, когда эта среда рассматривается как функция, преобразующая программы в их выходные данные. Куайны возможны в любом языке программирования, полном по Тьюрингу , как прямое следствие теоремы Клини о рекурсии . Для развлечения программисты иногда пытаются разработать максимально короткий куайн в любом заданном языке программирования .

Имя

Название «куайн» было придумано Дугласом Хофштадтером в его научно-популярной книге «Гёдель, Эшер, Бах » в честь философа Уилларда Ван Ормана Куайна (1908–2000), который провел обширное исследование косвенной самореференции и, в частности, следующего парадоксального выражения, известного как парадокс Куайна :

«Выдает ложь, если ему предшествует его цитата» выдает ложь, если ему предшествует его цитата.

История

Идея самовоспроизводящихся автоматов возникла на заре вычислительной техники, если не раньше. Джон фон Нейман теоретизировал о них в 1940-х годах. Позже, в 1972 году, Пол Брэтли и Джин Милло в своей статье «Computer Recreations: Self-Reproducing Automata» обсуждали их. [1] Брэтли впервые заинтересовался самовоспроизводящимися программами после того, как увидел первую известную такую ​​программу, написанную в Atlas Autocode в Эдинбурге в 1960-х годах преподавателем и исследователем Эдинбургского университета Хэмишем Дьюаром.

Требование «источника загрузки» в GNU Affero General Public License основано на идее квайна. [2]

Примеры

Конструктивные квины

В общем, метод, используемый для создания квайна на любом языке программирования, заключается в том, чтобы иметь в программе две части: (a)  код, используемый для фактической печати, и (b)  данные , представляющие текстовую форму кода. Код функционирует, используя данные для печати кода (что имеет смысл, поскольку данные представляют текстовую форму кода), но он также использует данные, обработанные простым способом, для печати текстового представления самих данных.

Вот три небольших примера на Python3:

# Пример A. chr(39) == "'". a  =  'a = {}{}{} ; print(a.format(chr(39), a, chr(39)))' ; print  ( a .format ( chr ( 39 ) , a , chr ( 39 )))  
# Пример B. chr(39) == "'". b  =  'b = %s%s%s ; print(b %% (chr(39), b, chr(39)))' ;  print ( b  %  ( chr ( 39 ),  b ,  chr ( 39 )))
# Пример C. %r будет заключаться в кавычки автоматически. c  =  'c = %r ; print(c %% c)' ;  print ( c  %  c )

Следующий код Java демонстрирует базовую структуру квайна.

public class Quine { public static void main ( String [] args ) { char q = 34 ; // Символ кавычек String [] l = { // Массив исходного кода "public class Quine" , "{" , " public static void main(String[] args)" , " {" , " char q = 34; // Символ кавычек" , " String[] l = { // Массив исходного кода" , " " , " };" , " for (int i = 0; i < 6; i++) // Вывести код открытия" , " System.out.println(l[i]);" , " for (int i = 0; i < l.length; i++) // Вывести массив строк" , " System.out.println(l[6] + q + l[i] + q + ',');" , " for (int i = 7; i < l.length; i++) // Распечатать этот код" , " System.out.println(l[i]);" , " }" , "}" , }; for ( int i = 0 ; i < 6 ; i ++ ) // Распечатать код открытия System . out . println ( l [ i ] ); for ( int i = 0 ; i < l . length ; i ++ ) // Распечатать массив строк System . out . println ( l [ 6 ] + q + l [ i ] + q + ',' ); for ( int i = 7 ; i < l . length ; i ++ ) // Распечатать этот код System . out . println ( l [ i ] ); } }                                                                             

Исходный код содержит массив строк, который выводится дважды, один раз в кавычках.

Этот код был адаптирован из оригинального поста с c2.com, где автор, Джейсон Уилсон, разместил его как минималистичную версию Quine, без комментариев Java. [3]

Благодаря новой функции текстовых блоков в Java 15 (или более поздней версии) возможна более читабельная и простая версия: [4]

public class Quine { public static void main ( String [] args ) { String textBlockQuotes = new String ( new char [] { '"' , '"' , '"' }); char newLine = 10 ; String source = """ public class Quine { public static void main(String[] args) { String textBlockQuotes = new String(new char[]{'"', '"', '"'}); char newLine = 10; String source = %s; System.out.print ( source.formatted (textBlockQuotes + newLine + source + textBlockQuotes)); } } " " " ; System.out.print ( source.formatted ( textBlockQuotes + newLine + source + textBlockQuotes ) ) ; } }                           

Эвал квинс

Некоторые языки программирования имеют возможность оценивать строку как программу. Quines могут воспользоваться этой возможностью. Например, этот Ruby quine:

eval s = "печать 'eval s=';p s" 

Lua может:

s = "print(string.format('s=%c%s%c; load(s)()',34,s,34))" ;  load ( s )()

В Python 3.8:

exec ( s := 'print("exec(s:= %r )" %s )' )

«Обманывающие» квайны

Самооценка

Во многих функциональных языках, включая Scheme и другие Lisp , а также интерактивных языках, таких как APL , числа являются самооценивающимися. В TI-BASIC , если последняя строка программы возвращает значение, возвращаемое значение отображается на экране. Поэтому в таких языках программа, состоящая только из одной цифры, приводит к 1-байтовому квайну. Поскольку такой код не конструирует сам себя, это часто считается мошенничеством.

1

Пустые квины

В некоторых языках, особенно скриптовых, а также в C , пустой исходный файл является фиксированной точкой языка, будучи допустимой программой, которая не выводит никаких данных. [a] Такая пустая программа, представленная как «самая маленькая в мире самовоспроизводящаяся программа», однажды выиграла приз за «худшее злоупотребление правилами» на Международном конкурсе запутанного кода на языке C. [ 5] Программа на самом деле не была скомпилирована, а использовалась cpдля копирования файла в другой файл, который можно было выполнить, чтобы ничего не вывести. [6]

Проверка исходного кода

Quines, по определению, не может получать никаких форм ввода, включая чтение файла, что означает, что quine считается "мошенничеством", если он смотрит на свой собственный исходный код. Следующий скрипт оболочки не является quine:

#!/bin/sh # Неверный квин. # Чтение исполняемого файла с диска — мошенничество.
cat $0 

Более короткий вариант, использующий поведение директив shebang :

#!/bin/кот

Другие сомнительные методы включают использование сообщений компилятора; например, в среде GW-BASIC ввод «Syntax Error» заставит интерпретатор ответить «Syntax Error».

Программы Уробороса

Концепция quine может быть расширена до нескольких уровней рекурсии, что приводит к появлению " программ уробороса ", или quine-реле. Это не следует путать с мультиquines.

Пример

Эта программа Java выводит исходный код для программы C++, которая выводит исходный код Java.

#include <iostream> #include <string> с использованием пространства имен std ;    int main ( int argc , char * argv []) { char q = 34 ; string l [] = { " " , "=============<<<<<<< Код на C++ >>>>>>>>=============" , "#include <iostream>" , "#include <string>" , "используя пространство имен std;" , "" , "int main(int argc, char* argv[])" , "{" , " char q = 34;" , " string l[] = {" , " };" , " for(int i = 20; i <= 25; i++)" , " cout << l[i] << endl;" , " for(int i = 0; i <= 34; i++)" , " cout << l[0] + q + l[i] + q + ',' << endl;" , " for(int i = 26; i <= 34; i++)" , " cout << l[i] << endl;" , " return 0;" , "}" , "============<<<<<<< Код Java >>>>>>>>==============" , "public class Quine" , "{" , " public static void main(String[] args)" , " {" , " char q = 34;" , " String[] l = {" , " };" , " for(int i = 2; i <= 9; i++)" , " System.out.println(l[i]);" , " for(int i = 0; i < l.length; i++)" , " System.out.println(l[0] + q + l[i] + q + ',');" , " for(int i = 10; i <= 18; i++)" , " System.out.println(l[i]);" , " }" , "}" ,}; для ( int i = 20 ; i <= 25 ; i ++ ) cout << l [ i ] << endl ; для ( int i = 0 ; i <= 34 ; i ++ ) cout << l [ 0 ] + q + l [ i ] + q + ',' << endl ; для (                                                                                   int i = 26 ; i <= 34 ; i ++ ) cout << l [ i ] << endl ; return 0 ; }              
public class Quine { public static void main ( String [] args ) { char q = 34 ; String [] l = { " " , "=============<<<<<<< Код на C++ >>>>>>>>==============" , "#include <iostream>" , "#include <string>" , "используя пространство имен std;" , "" , "int main(int argc, char* argv[])" , "{" , " char q = 34;" , " string l[] = {" , " };" , " for(int i = 20; i <= 25; i++)" , " cout << l[i] << endl;" , " for(int i = 0; i <= 34; i++)" , " cout << l[0] + q + l[i] + q + ',' << endl;" , " for(int i = 26; i <= 34; i++)" , " cout << l[i] << endl;" , " return 0;" , "}" , "============<<<<<<< Код Java >>>>>>>>==============" , "public class Quine" , "{" , " public static void main(String[] args)" , " {" , " char q = 34;" , " String[] l = {" , " };" , " for(int i = 2; i <= 9; i++)" , " System.out.println(l[i]);" , " for(int i = 0; i < l.length; i++)" , " System.out.println(l[0] + q + l[i] + q + ',');" , " for(int i = 10; i <= 18; i++)" , " System.out.println(l[i]);" , " } " , "}" , }; for ( int i = 2 ; i <= 9 ; i ++ ) System .out .println ( l [ i ] ) ; for ( int i = 0 ; i < l.length ; i ++ ) System.out.println ( l [ 0 ] + q +                                                                          l [ i ] + q + ' ,' ) ; for ( int i = 10 ; i < = 18 ; i ++ ) System.out.println ( l [ i ] ) ; } }              

Такие программы были созданы с различной продолжительностью цикла:

Мультихины

Дэвид Мадор, создатель Unlambda , описывает мультиквины следующим образом: [16]

«Мультиквайн — это набор из r различных программ (на r различных языках — без этого условия мы могли бы считать их все равными одному квайну), каждая из которых способна распечатать любую из r программ (включая себя) в соответствии с переданным ей аргументом командной строки. (Обман не допускается: аргументы командной строки не должны быть слишком длинными — передача полного текста программы считается обманом)».

Мультиквайном, состоящим из 2 языков (или биквайном), будет программа, которая:

Тогда биквину можно рассматривать как набор из двух программ, каждая из которых способна вывести на печать любую из двух программ в зависимости от переданного аргумента командной строки.

Теоретически, нет ограничений на количество языков в мультиквине. Мультиквин из 5 частей (или пентаквин) был создан с помощью Python , Perl , C , NewLISP и F# [17] , а также существует мультиквин из 25 языков. [18]

Полиглот

Похожая на мультиквин, но в отличие от мультиквина, программа -полиглот — это компьютерная программа или скрипт, написанный в допустимой форме нескольких языков программирования или форматов файлов путем объединения их синтаксиса. Программа-полиглот не обязана обладать качеством самовоспроизводства, хотя программа-полиглот также может быть квином в одном или нескольких возможных способах выполнения.

В отличие от квайнов и мультиквайнов, полиглот-программы не гарантированно существуют между произвольными наборами языков в результате теоремы Клини о рекурсии, поскольку они полагаются на взаимодействие между синтаксисами, а не на доказуемое свойство, согласно которому один язык всегда может быть встроен в другой.

Радиационно-стойкий

Радиационно-устойчивый квин — это квин, из которого можно удалить любой одиночный символ, и который все равно будет производить исходную программу без отсутствующих символов. По необходимости такие квины гораздо более запутанны, чем обычные квины, как видно из следующего примера на Ruby : [19]

eval = 'eval$q=%q(puts %q(10210/ #{ 1 1 if 1 == 21 } }/.i спасение##/   1 1"[13,213].max_by{|s|s.size}#"##").gsub(/\d/){["= \47 eval$q=%q( #$q )# \47 ## \47",:eval,:instance_,"||=9"][eval$&]} выход)#' ##'instance_eval = 'eval$q=%q(puts %q(10210/ #{ 1 1 if 1 == 21 } }/.i спасение##/   1 1"[13,213].max_by{|s|s.size}#"##").gsub(/\d/){["= \47 eval$q=%q( #$q )# \47 ## \47",:eval,:instance_,"||=9"][eval$&]} выход)#' ##'/ #{ eval eval if eval == instance_eval } }/ . я спасаю ##/    eval eval "[eval||=9,instance_eval||=9].max_by{|s|s.size}#" ##" 

Автоматическая генерация

Используя методы реляционного программирования , можно автоматически генерировать квайны, преобразуя интерпретатор (или, что эквивалентно, компилятор и среду выполнения) языка в реляционную программу, а затем решая для фиксированной точки . [20]

Смотрите также

Примечания

  1. ^ Примеры включают Bash , Perl и Python.

Ссылки

  1. ^ Bratley, Paul; Millo, Jean (1972). «Компьютерные развлечения: самовоспроизводящиеся автоматы». Программное обеспечение: практика и опыт . 2 (4): 397–400. doi :10.1002/spe.4380020411. S2CID  222194376.
  2. ^ Kuhn, Bradley M. (21 ноября 2007 г.). "stet и AGPLv3". Software Freedom Law Center. Архивировано из оригинала 15 марта 2008 г. Получено 14 июня 2008 г.
  3. ^ "Программа Куайна". wiki.c2.com .
  4. ^ "Простой Java Quine, самовоспроизводящийся (самокопирующийся) код Java с текстовыми блоками. Этот код может быть запущен с Java 15+ или Java 13+ со специальными флагами. Лицензия является общественным достоянием, права не защищены".
  5. ^ "IOCCC 1994 Худшее нарушение правил". Архивировано из оригинала 12 ноября 2020 г.
  6. ^ "Makefile". IOCCC.org . Архивировано из оригинала 23 апреля 2019 . Получено 4 апреля 2019 .
  7. Дэн Пипони (5 февраля 2008 г.). «Квайн третьего порядка на трех языках».
  8. ^ Брюс Эдигер. "Просите и дано будет вам: самовоспроизводящаяся программа, проходящая через три поколения, Python, Bash, Perl". Архивировано из оригинала 2011-02-23 . Получено 2011-03-17 .
  9. ^ bm (1 февраля 2011). "multiquine". Архивировано из оригинала 2013-04-15.
  10. ^ Дэн Пипони (30 января 2011 г.). «Куайн Сентрал».
  11. Руслан Ибрагимов (20 апреля 2013 г.). "Quine Ruby -> Java -> C# -> Python" (на русском языке). Архивировано из оригинала 4 марта 2016 г. Получено 20 апреля 2013 г.
  12. Шиничиро Хамадзи (10 ноября 2007 г.). «Quine by shinh (C C++ Ruby Python PHP Perl)».(этот тоже полиглот )
  13. ^ Ku-ma-me (22 сентября 2009 г.). "Uroboros Programming With 11 Programming Languages". Архивировано из оригинала 29 августа 2011 г. Получено 17 марта 2011 г.
  14. ^ Юсукэ Эндо (2 ноября 2021 г.). «Quine Relay — программа uroboros с более чем 100 языками программирования». GitHub .
  15. ^ Майкл Вехар (10 ноября 2019 г.). «C печатает JavaScript».
  16. ^ Дэвид Мадор. «Квайны (самовоспроизводящиеся программы)».
  17. Рейнард ван Тондер (14 января 2020 г.). «Пентахин – мультихин 5 частей». Гитхаб .
  18. ^ Лу Ванг (21 мая 2021 г.). «Quine Chameleon#Variants». GitHub .
  19. ^ Юсукэ Эндо. «Радиоустойчивый Куайн». GitHub . Получено 24.02.2014 .
  20. ^ Берд, Уильям Э.; Холк, Эрик; Фридман, Дэниел П. (2012-09-09). "MiniKanren, живой и немаркированный: генерация Quine через реляционные интерпретаторы (Programming Pearl)" (PDF) . Труды ежегодного семинара 2012 года по схемам и функциональному программированию . Scheme '12. Нью-Йорк, штат Нью-Йорк, США: Ассоциация вычислительной техники. стр. 8–29. doi :10.1145/2661103.2661105. ISBN 978-1-4503-1895-2.

Дальнейшее чтение

Внешние ссылки