Как написать самовоспроизводящийся код (печатает исходники на exec)? - PullRequest
32 голосов
/ 20 сентября 2008

Я видел множество решений этой проблемы на основе C / C ++, где мы должны написать программу, которая при выполнении печатает свой собственный источник.

некоторые решения -

http://www.cprogramming.com/challenges/solutions/self_print.html

Решение Quine Page на многих языках

Есть еще много решений в сети, каждое из которых отличается от другого. Интересно, как мы подходим к такой проблеме, что идет в голову тому, кто ее решает. Дайте мне некоторое представление об этой проблеме ... Хотя решения в интерпретируемых языках, таких как perl, php, ruby ​​и т. Д., Могут быть простыми ... я хотел бы знать, как можно разработать его на компилируемых языках ...

Ответы [ 11 ]

53 голосов
/ 20 сентября 2008

Помимо читерства¹ нет никакой разницы между компилируемыми и интерпретируемыми языками.

Общий подход к кваи довольно прост. Во-первых, как бы программа ни выглядела, в какой-то момент она должна что-то напечатать:

print ...

Однако, что это должно напечатать? Сам. Так что нужно распечатать команду «печать»:

print "print ..."

Что должно быть напечатано дальше? Ну, в то время как программа выросла, поэтому она должна напечатать строку, начинающуюся также с «print»:

print "print \"print ...\""

Теперь программа снова выросла, так что есть еще что напечатать:

print "print \"print \\\"...\\\"\""

И так далее. С каждым добавленным кодом появляется больше кода для печати. Такой подход ни к чему не приведет, но это показывает интересную закономерность: Строка "print \" "повторяется снова и снова. Было бы неплохо поставить повторяющуюся часть в переменную:

a = "print \""
print a

Однако программа просто изменилась, поэтому нам нужно настроить:

a = "a = ...\nprint a"
print a

Когда мы сейчас попытаемся заполнить "...", мы сталкиваемся с теми же проблемами, что и раньше. В конечном итоге мы хотим написать что-то вроде этого:

a = "a = " + (quoted contents of a) + "\nprint a"
print a

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

a = "a = " + quoted(a) + "\nprint a"
print a

Таким образом, единственное, что мы можем сделать, это поместить заполнитель в a:

a = "a = @\nprint a"
print a

И в этом весь трюк! Все остальное теперь понятно. Просто замените держатель с указанным содержанием a:

a = "a = @\nprint a"
print a.replace("@", quoted(a))

Поскольку мы изменили код, нам нужно настроить строку:

a = "a = @\nprint a.replace(\"@\", quoted(a))"
print a.replace("@", quoted(a))

И это все! Все quines на всех языках работают таким образом (кроме читерских).

Ну, вы должны убедиться, что вы заменяете только первый случай заполнителя. И если вы используете второй место, Вы можете избежать цитирования строки.

Но это мелкие проблемы и легко решить. Если факт, реализация quoted() и replace() единственные детали, в которых различные квины действительно отличаются.


¹, заставив программу прочитать исходный файл

9 голосов
/ 20 сентября 2008

Существует несколько различных стратегий написания цитат. Очевидным является просто написать код, который открывает код и печатает его. Но более интересные из них включают языковые функции, которые допускают самостоятельное встраивание, такие как функция% s в стиле printf во многих языках. Вы должны выяснить, как встраивать что-то, чтобы оно в конечном итоге разрешалось встраивать запрос. Я подозреваю, что, как и палиндромы, много проб и ошибок.

2 голосов
/ 20 сентября 2008

Также вы можете изучить, как работает игра Core Wars. Думаю, это был бы хороший пример.

1 голос
/ 12 октября 2008

Ради интереса, я придумал один в Схеме, которым я очень гордился около 5 минут, пока не обнаружил, что он был обнаружен ранее. В любом случае, есть небольшие изменения в «правилах» игры для лучшего учета двойственности данных и кода в Лиспе: вместо распечатки исходного кода программы это S-выражение, которое возвращает себя:

((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))

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

1 голос
/ 20 сентября 2008

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

Обман включает в себя: - Использование интерпретированного языка и просто загрузка источника и его печать - файлы длиной 0 байт, которые действительны в некоторых языках, таких как C.

0 голосов
/ 11 декабря 2013

Я сделал пример AS3 для тех, кто заинтересован в этом

var program = "var program = @; function main(){trace(program.replace('@', 

String.fromCharCode(34) + program + String.fromCharCode(34)))} main()"; 
function main(){
   trace(program.replace('@', String.fromCharCode(34) + program + String.fromCharCode(34)))
}
main()
0 голосов
/ 02 августа 2013

В python вы можете написать:

s='c=chr(39);print"s="+c+s+c+";"+s';c=chr(39);print"s="+c+s+c+";"+s

вдохновленный этим самопечатающимся псевдокодом:

Print the following line twice, the second time with quotes.
"Print the following line twice, the second time with quotes."
0 голосов
/ 01 января 2013

Как насчет чтения и распечатки исходного кода? Это совсем не сложно! Вот один в php:

<?php
{
header("Content-Type: text/plain");
    $f=fopen("5.php","r");
    while(!feof($f))
    {
        echo fgetc($f);
    } 
    fclose($f);
}
?>
0 голосов
/ 20 сентября 2008

Вы можете найти немало решений здесь: http://forums.thedailywtf.com/forums/p/5232/147528.aspx

0 голосов
/ 20 сентября 2008

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

...