Как написать самовоспроизводящийся код (печатает исходный код в exec)?

StackOverflow https://stackoverflow.com/questions/105725

  •  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 _ _)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top