Как написать код самовоспроизводящегося (печатает источник на exec)?
Я видел много решений на основе C/С++ для этой проблемы, где мы должны написать программу, которая после выполнения печатает свой собственный источник.
некоторые решения -
http://www.cprogramming.com/challenges/solutions/self_print.html
Решение на уровне страницы на многих языках
В сети есть еще много решений, каждый из которых отличается от другого. Интересно, как мы подходим к такой проблеме, что входит в ум того, кто ее решает. Предоставьте мне некоторое представление об этой проблеме... Хотя решения в интерпретируемых языках, таких как perl, php, ruby и т.д., Могут быть легкими... Я хотел бы знать, как это можно сделать для составления его на скомпилированных языках...
Ответы
Ответ 1
Помимо обмана № нет разницы между скомпилированными и интерпретируемыми языками.
Общий подход к quines довольно прост. Во-первых, независимо от того, какая программа выглядит, в какой-то момент она должна что-то печатать:
print ...
Однако, что он должен печатать? Сам. Поэтому ему нужно распечатать команду "print":
print "print ..."
Что следует напечатать дальше? Ну, тем временем программа выросла, поэтому ей также нужно напечатать строку, начинающуюся с "print":
print "print \"print ...\""
Теперь программа снова росла, поэтому снова напечатано:
print "print \"print \\\"...\\\"\""
И так далее.
С каждым добавленным кодом есть еще код для печати.
Этот подход никуда не денется,
но он показывает интересную картину:
Строка "print \" "повторяется снова и снова.
Было бы неплохо поставить повторяющуюся часть
в переменную:
a = "print \""
print a
Однако программа просто изменилась,
поэтому нам нужно настроить 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()
являются единственными деталями, в которых различные quines действительно отличаются.
¹, заставляя программу читать исходный файл
Ответ 2
Существует несколько различных стратегий написания quines. Очевидным является просто написать код, который открывает код и распечатывает его. Но более интересные из них связаны с языковыми функциями, которые позволяют самообучаться, например, функция printf% s-стиля на многих языках. Вы должны выяснить, как внедрить что-то, чтобы оно в конечном итоге разрешило запрос, который нужно встроить. Я подозреваю, что, подобно палиндромам, много проб и ошибок.
Ответ 3
Несколько учебников по quines: здесь и здесь.
Ответ 4
Также вы могли бы изучить, как работает игра в Core Wars. Думаю, это будет хороший пример.
Ответ 5
Обычный подход (когда вы не можете обмануть *) заключается в том, чтобы написать что-то, что кодирует его источник в строковой константе, затем дважды печатает эту константу: один раз как строковый литерал и один раз в качестве кода. Это оборачивается "каждый раз, когда я пишу строку кода, я должен написать другую, чтобы распечатать ее!" проблема.
"Обман" включает в себя:
- Использование интерпретируемого языка и просто загрузка источника и его печать
- файлы длиной 0 байтов, которые действительны на некоторых языках, например C.
Ответ 6
Сайт с примерами тонн:
http://www.nyx.net/~gthompso/quine.htm
Ответ 7
Для удовольствия я придумал один в Scheme, который я очень гордился около 5 минут, пока я не обнаружил, что был обнаружен раньше. В любом случае, есть небольшая модификация "правил" игры, чтобы лучше рассчитывать на двойственность данных и кода в Lisp: вместо того, чтобы печатать исходный код программы, это S-выражение, которое возвращает себя:
((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))
один в Википедии имеет ту же концепцию, но с немного другим (более подробным) механизмом цитирования. Мне нравится мое лучше, хотя.
Ответ 8
Одна идея подумать о кодировании и о том, как дать что-то двойное значение, чтобы его можно было использовать для вывода чего-то в нескольких формах. Существует также cavaet, что проблема такого типа связана с ограничениями, чтобы сделать его более сложным, так как без каких-либо правил, отличных от самого выхода программы, пустая программа является решением.
Ответ 9
Вы можете найти здесь несколько решений: http://forums.thedailywtf.com/forums/p/5232/147528.aspx
Ответ 10
Как насчет собственно чтения и печати исходного кода? Это не сложно! Heres one in php:
<?php
{
header("Content-Type: text/plain");
$f=fopen("5.php","r");
while(!feof($f))
{
echo fgetc($f);
}
fclose($f);
}
?>
Ответ 11
В 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."
Ответ 12
Я сделал пример 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()
Ответ 13
В рубине:
помещает File.read(_ _ FILE _ _)