Программа quine, или quine, - это программа, которая при выполнении печатает свой собственный исходный код. Программа quine не должна "выходить за пределы себя", например, печатать содержимое файла, в котором она находится, или использовать интроспективные возможности для печати своего собственного представления. Вместо этого она должна вычислять свой собственный исходный код.
Классический способ создания такой программы состоит из двух шагов:
- Инициализируйте строковую переменную, в которой будет содержаться место для интерполяции.
- Выведите строку и интерполируйте ее в себя.
Как это сделать, зависит от языка, от объявления переменных, необходимости точек с запятой и перевода строки, требуемых кавычек и т. д. Работа с кавычками очень интересна: нужно найти способ указать, что кавычка должна быть напечатана, не используя кавычки на самом деле.
Bash
Как и большинство вещей в Bash, эта программа использует интересную причуду. Хотя одинарные кавычки являются сильными кавычками и ничего не расширяют, но printf
восьмеричные управляющие символы как символы с указанной кодовой точкой:
s='s=%s;printf "$s" "$s"';printf "$s" "$s"
Python
В Python идентификатор формата %r
Самый простой способ сделать это - завершить код символом новой строки:
s='s=%r;print(s%%s)';print(s%s)
Если вы хотите получить код без переноса строки, напишите следующее:
s='s=%r;print(s%%s,sep="")';print(s%s,sep="")
JavaScript
Следующие JavaScript-кины работают под управлением node.js. Они используют console.log
, который всегда добавляет новую строку, так что в конце каждого сценария требуется новая строка:
s="s=%j;console.log(s,s)";console.log(s,s)
Следующая программа также интересна: она не выводит полное представление, но опирается на тот факт, что функции имеют определенное представление:
(function a(){console.log('('+a+')()')})()
Следующий пример близок к мошенничеству, поскольку он eval
используется:
code='var q=unescape("%27");console.log("code="+q+code+q+";eval(code)")';eval(code)
Ржавчина
Rust предоставляет возможность заключить аргумент в кавычки в макросе печати с форматированием, но этот макрос требует, чтобы первый аргумент макроса печати был строковым литералом! Поэтому лучше всего использовать позиционный идентификатор аргумента:
fn main(){print!("fn main(){{print!({0:?},{0:?})}}","fn main(){{print!({0:?},{0:?})}}")}
PHP
Эта PHP-программа работает, сохраняя исходный код в строке символов, а затем используя printf
Сайт 39
обозначает символ ASCII '
, чтобы правильно обрабатывать инвертированные запятые в строке:
<?php
$code = '<?php
$code = %c%s%c;
printf($code, 39, $code, 39);
';
printf($code, 39, $code, 39);
HQ9+
Последним, но не менее важным, является HQ9+, который был разработан Клиффом Биффлом.:
Q