Как написать самовоспроизводящийся код (печатает исходный код на exec)?
Я видел множество решений этой проблемы на основе C/C++, где мы должны написать программу, которая после выполнения печатает свой собственный источник.
некоторые решения -
http://www.cprogramming.com/challenges/solutions/self_print.html
Решение Quine Page на многих языках
В сети есть еще много решений, каждое из которых отличается от другого. Интересно, как мы подходим к такой проблеме, что идет в голову тому, кто ее решает. Дайте мне некоторое представление об этой проблеме... Хотя решения в интерпретируемых языках, таких как perl, php, ruby и т. Д., Могут быть простыми... я хотел бы знать, как можно разработать его на скомпилированных языках...
11 ответов
Помимо обмана… нет никакой разницы между компилируемыми и интерпретируемыми языками.
Общий подход к кваи довольно прост. Во-первых, какой бы ни была программа, в какой-то момент она должна что-то напечатать:
Распечатать...
Однако, что это должно напечатать? Сам. Так что нужно распечатать команду "печать":
печать "печать..."
Что должно быть напечатано дальше? Ну, в то время как программа росла, поэтому она должна напечатать строку, начинающуюся также с "print":
печать "печать \" печать... \ ""
Теперь программа снова выросла, так что есть еще что напечатать:
печать "печать \" печать \\\ "... \\\" \ ""
И так далее. С каждым добавленным кодом появляется больше кода для печати. Этот подход ни к чему не приводит, но он обнаруживает интересную закономерность: строка "print \" повторяется снова и снова. Было бы неплохо поместить повторяющуюся часть в переменную:
a = "print \" " распечатать
Однако программа просто изменилась, поэтому нам нужно настроить:
a = "a =... \ nprint a" распечатать
Когда мы сейчас пытаемся заполнить "...", мы сталкиваемся с теми же проблемами, что и раньше. В конечном итоге мы хотим написать что-то вроде этого:
a = "a =" + (цитируемое содержимое a) + "\nprint a" распечатать
Но это невозможно, потому что даже если бы у нас была такая функция quoted()
для цитирования, есть еще проблема, которую мы определяем a
с точки зрения самого себя:
a = "a =" + quoted (a) + "\nprint a" распечатать
Таким образом, единственное, что мы можем сделать, это поместить заполнитель в a
:
a = "a = @ \ nprint a" распечатать
И в этом весь трюк! Все остальное теперь понятно. Просто замените заполнитель цитируемым содержанием a
:
a = "a = @ \ nprint a" print a.replace ("@", цитата (а))
Поскольку мы изменили код, нам нужно настроить строку:
a = "a = @ \ nprint a.replace (\" @ \ ", quoted (a))" print a.replace ("@", цитата (а))
И это все! Все квины на всех языках работают таким образом (кроме мошеннических).
Что ж, вы должны убедиться, что вы заменили только первый случай использования заполнителя. И если вы используете второе место, вы можете избежать цитирования строки.
Но это мелкие проблемы, которые легко решить. Если факт, реализация quoted()
а также replace()
являются единственными деталями, в которых различные цитрусовые действительно отличаются.
Making заставив программу прочитать исходный файл
Есть несколько разных стратегий написания цитат. Очевидным является просто написать код, который открывает код и печатает его. Но более интересные из них включают языковые функции, которые допускают самостоятельное встраивание, такие как функция% s в стиле printf во многих языках. Вы должны выяснить, как встраивать что-то, чтобы оно в конечном итоге разрешалось встраивать запрос. Я подозреваю, как и палиндромы, много проб и ошибок.
Также вы можете изучить, как работает игра Core Wars. Я думаю, это был бы хороший пример.
Для забавы я придумал один в Схеме, которым я очень гордился около 5 минут, пока не обнаружил, что он был обнаружен ранее. В любом случае, есть небольшие изменения в "правилах" игры для лучшего учета двойственности данных и кода в Лиспе: вместо распечатки исходного кода программы это S-выражение, которое возвращает себя:
((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))
Тот, что в Википедии, имеет ту же концепцию, но с немного другим (более подробным) механизмом цитирования. Мне больше нравится мой, хотя.
Сайт с множеством примеров:
http://www.nyx.net/~gthompso/quine.htm
Обычный подход (когда вы не можете обмануть *) состоит в том, чтобы написать что-то, что кодирует его источник в строковой константе, затем распечатывает эту константу дважды: один раз как строковый литерал и один раз как код. Это звучит так: "Каждый раз, когда я пишу строку кода, я должен написать другую, чтобы распечатать ее!" проблема.
"Обман" включает в себя: - использование интерпретированного языка и простую загрузку источника и его печать - файлы длиной 0 байт, которые допустимы в некоторых языках, таких как C.
В 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."
Вы можете найти немало решений здесь: http://forums.thedailywtf.com/forums/p/5232/147528.aspx
Как насчет чтения и печати вашего исходного кода? Это совсем не сложно! Вот один в php:
<?php
{
header("Content-Type: text/plain");
$f=fopen("5.php","r");
while(!feof($f))
{
echo fgetc($f);
}
fclose($f);
}
?>
Одна идея подумать о кодировании и о том, как придать что-то двойное значение, чтобы его можно было использовать для вывода чего-либо в нескольких формах. Есть также кавет, что этот тип проблемы идет с ограничениями, чтобы усложнить его, поскольку без каких-либо правил, кроме самой программы, пустая программа является решением.
Я сделал пример 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()
В bash это действительно просто
сенсорный тест; chmod oug+x test; ./контрольная работа
Пустой файл, пустой вывод