Как написать самовоспроизводящийся код (печатает исходный код в exec)?
-
01-07-2019 - |
Вопрос
Я видел много решений этой проблемы на основе C / C ++, где мы должны написать программу, которая при выполнении печатает свой собственный исходный код.
некоторые решения --
http://www.cprogramming.com/challenges/solutions/self_print.html
Решение страницы Quine на многих языках
В сети существует еще множество решений, каждое из которых отличается от другого.Интересно, как мы подходим к такой проблеме, что происходит в голове у того, кто ее решает.Дайте мне некоторое представление об этой проблеме...В то время как решения на интерпретируемых языках, таких как perl, php, ruby и т.д., Могут быть простыми...я хотел бы знать, как можно спроектировать это на скомпилированных языках...
Решение
Помимо мошенничества1, нет никакой разницы между скомпилированными и интерпретируемыми языками.
Общий подход к quines довольно прост.Во-первых, как бы ни выглядела программа, в какой-то момент она должна что-то напечатать:
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))
И это все!Все квайны на всех языках работают именно так (за исключением читерских).
Что ж, вам следует убедиться, что вы заменяете только держатель для замены в первом случае.И если вы используете второй заменитель, вы можете избежать необходимости заключать строку в кавычки.
Но это незначительные проблемы
и их легко решить.Если на самом деле, то реализация quoted()
и replace()
это единственные детали, в которых различные куайны действительно отличаются друг от друга.
1 заставив программу прочитать свой исходный файл
Другие советы
Существует несколько различных стратегий написания куайнов.Очевидный вариант - просто написать код, который открывает код и распечатывает его.Но более интересные из них связаны с языковыми функциями, которые допускают самостоятельное встраивание, такими как функция printf в стиле %s на многих языках.Вы должны выяснить, как внедрить что-то так, чтобы в конечном итоге это соответствовало запросу на внедрение.Я подозреваю, что, как и в случае с палиндромами, здесь требуется много проб и ошибок.
Также вы могли бы изучить, как работает игра Core Wars.Я думаю, это был бы хороший пример.
Обычный подход (когда вы не можете обмануть *) состоит в том, чтобы написать что-то, что кодирует свой источник в строковой константе, а затем дважды выводит эту константу:Один раз как строковый литерал, и один раз как код.Это позволяет обойти проблему "каждый раз, когда я пишу строку кода, мне приходится писать другую, чтобы распечатать ее!".
"Мошенничество" включает в себя:- Использование интерпретируемого языка и простая загрузка исходного кода и его печать - Файлы длиной 0 байт, которые допустимы для некоторых языков, таких как C.
Забавы ради я придумал один из них в Scheme, которым я очень гордился около 5 минут, пока не обнаружил, что он был обнаружен раньше.В любом случае, есть небольшая модификация "правил" игры, чтобы лучше учитывать двойственность данных и кода в Lisp:вместо того, чтобы распечатывать исходный код программы, это S-выражение, которое возвращает само себя:
((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))
Тот Самый один из них в Википедии имеет ту же концепцию, но с немного другим (более подробным) механизмом цитирования.Хотя мой мне нравится больше.
Одна из идей - подумать о кодировании и о том, как придать чему-либо двойное значение, чтобы его можно было использовать для вывода чего-либо в нескольких формах.Существует также оговорка, что этот тип проблемы сопровождается ограничениями, усложняющими ее, поскольку без каких-либо правил, отличных от самого вывода программы, пустая программа является решением.
Вы можете найти довольно много решений для этого здесь: 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);
}
?>
В 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."
Я сделал пример 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()
В ruby:
помещает файл.read(_ _ FILE _ _)