Pull to refresh

Comments 56

Вы, по-видимому, не читали данную в статье ссылку. Там прямо в первом абзаце сказано, что LIST — является грязным хаком.
некоторым людям нравятся грязные хаки
Можно еще на 1 байт сократить размер программы. Тогда будет работать на большем количестве языков, а не только на HQ9+. :-)
Вырождение программы до нулевого размера также не является квайном
Только после этого случая: www0.us.ioccc.org/1994/smr.hint

In the future, the contest rules will specify a minimum size that is one character larger than this entry, forever eliminating this sort of program from contest. After all, how many variations can one make on this entry? :-)
хм, а к чему это? Я понимаю так — если бы выходные данные можно было подать в качестве входных данных, модифицировать, перекомпилировать, а за тем снова использовать в качестве выходного параметра для самой себя было намного интереснее. Избавляться от рекурсии тут совершенно зря. Рекурсия нужна, встает только вопрос что лучше использовать в качестве выходной стоки для разбора, исходный язык программирования, бинарную строку или нечто промежуточное, типа байт кода.
Оба варианта допустимы.

> Куайн, квайн (англ. quine) — компьютерная программа, которая выдаёт на выходе точную копию своего исходного текста. Следует заметить, что программы, использующие внешние данные, куайнами не считаются; то есть исключается прочтение текста программы из файла, ввод его с клавиатуры и так далее. Кроме того, не считается куайном «программа», не содержащая вообще никакого кода (вырожденный случай). (с) Wikipedia
Попробуем написать квайн. Для этого возьмём инструкцию языка для вывода и передадим ей как параметр код программы. Однако в коде мы снова используем этот же код и так далее — возникает бесконечная рекурсия. Но что можно сделать для того, чтобы не передавать строковую константу? Решение — поместить строку (копию части кода) в переменную. Для удобства назовём такую строку s-строкой, а переменную с этой строкой — s-переменной. Чтобы и в s-переменной не было рекурсии, мы просто исключим из неё фрагмент задания этой самой переменной. То есть, выглядит это примерно так:

C:
const char *s=«const char *s=;»;


Вы решили взорвать мой мозг, чтобы в понедельник я на работу не вышел? ) Интересная ПЕРЕМЕНная с модификатором const, причем не содержащая «фрагмент задания этой самой переменной» «const char *s=;»
Ухты, спасибо =) В принципе мысль и так была понятна, просто спросонья решил побурчать…
Наверно самый простой квайн это в бинарнике (если считать что бинарник это самый машинный язык), открыть свой исполняемый на чтение и вывести в хексах или в бине.
> Куайн, квайн (англ. quine) — компьютерная программа (частный случай метапрограммирования), которая выдаёт на выходе точную копию своего исходного текста. Следует заметить, что программы, использующие внешние данные, куайнами не считаются; то есть исключается прочтение текста программы из файла, ввод его с клавиатуры и так далее. Кроме того, не считается куайном «программа», не содержащая вообще никакого кода (вырожденный случай).
Хороший квайн на питоне нашёл. Сохранить в файл fail.py и запустить:

File «fail.py», line 1
File «fail.py», line 1
^
IndentationError: unexpected indent

UFO just landed and posted this here
Вернее
seek( DATA, 0, 0 );
print <DATA>;
__DATA__;
Более того, мы не будем использовать «хаки» интерпретеруемых языков вроде операции вывода исходного кода и функций типа eval

Простите, а можно поподробнее про вывод кода программы с помощью операции вывода кода программы или функции eval()? На питоне, например.
Даже не подозревал о таком.
Конечно, сразу код так не вывести, но часто это может значительно упростить задачу: только лишь присвоили переменной код, вывели код и исполнили код.
JavaScript (Mozilla JaggerMonkey) с выводом в консоль:
(function quine() {
    console.log("(" + quine.toString() + "())");
}())

Т.к. движков JavaScript много, то универсальный квайн написать нельзя
Думаю это тоже читерство, но вот более переносимая версия, правда для другого языка. :] Если сделать (setf *print-pretty* nil), то любая реализация должна вывести одинаково:

(DEFUN QUINE NIL (WRITE (APPEND (QUOTE (DEFUN QUINE NIL)) (CDDR (THIRD (FUNCTION-LAMBDA-EXPRESSION (FUNCTION QUINE)))))) (WRITE (QUOTE (QUINE))))(QUINE)

Вот версия с pretty print'ом, но её разные реализации могут с отличиями выводить:

(DEFUN QUINE ()
  (WRITE
    (APPEND '(DEFUN QUINE ())
                    (CDDR (THIRD (FUNCTION-LAMBDA-EXPRESSION #'QUINE)))))
  (WRITE '(QUINE)))(QUINE)
Можно короче

(function () {
    console.log("(" + arguments.calee.toString() + "())");
}())
Без строк. :P

(=> — это вывод системы)

(progn (defparameter s '(progn (defparameter s) (write (list (first s) (append (second s) (list `',s)) (third s))))) (write (list (first s) (append (second s) (list `',s)) (third s))))

=> (progn (defparameter s '(progn (defparameter s) (write (list (first s) (append (second s) (list `',s)) (third s))))) (write (list (first s) (append (second s) (list `',s)) (third s))))

(eval *) ; Попробуем выполнить результат

=> (progn (defparameter s '(progn (defparameter s) (write (list (first s) (append (second s) (list `',s)) (third s))))) (write (list (first s) (append (second s) (list `',s)) (third s))))

(equalp ** ++) ; равна ли позапрошлая команда тому что она выводит

=> t               ; true :)
Python-читерство =))

print(open(__file__).read())
Штуки как <?php echo file_get_contents(__FILE__); ?> квайнами не сичтаются: «исключается прочтение текста программы из файла» — из википедии.
Мне просто надоело уже википедию копировать, ведь не первый раз уже.
Какое практическое применение квайнов? Тема интересная, но пока не могу понять где в практике можно использовать.
По оценкам за мои два комментария в этом топике можно подумать что капитанство оценивается на Хабре выше чем написание квайнов.
Хабр такой хабр.
Также как и решение задач, головоломок ребусов и тд. в реальной жизни мало где находят применения, однако ж действия сии заставляют мозги работать и держат их в тонусе. Так что польза от этого все же есть.
На собеседовании могут спросить
<?php printf($a='<?php printf($a=%c%s%c,39,$a,39);',39,$a,39);
А порядок вычисления параметров фукции гарантируется? Точно ли присваивание выполнится до использования $a в качестве третьего параметра? И не надо ли закрыть скобку?
гарантируется. точно. какую?
Парную к <?php? Или она и не должна закрываться?
На windows cmd считается за квайн?
<---cut--->
@type %0
<---cut--->
Или это тоже грязный хак?
Скорей всего хак. Т.к. явно читает код собственной программы.
main = putStr (s ++ show s) where s = «main = putStr (s ++ show s) where s = „
чисто для отчетности

Java

package ru.fso.test;public class Quine {public static void main(String[] args) {char sq = '"';String cf = "%c";String sf = "%s";String s = "package ru.fso.test;public class Quine {public static void main(String[] args) {char sq = '%c';String cf = %c%s%c;String sf = %c%s%c;String s = %c%s%c;System.out.println(String.format(s,sq,sq,cf,sq,sq,sf,sq,sq,s,sq));}}";System.out.println(String.format(s,sq,sq,cf,sq,sq,sf,sq,sq,s,sq));}}
А я ещё стопицот таких «квайнов» на лиспе знаю:

«a»
«aa»
«aaa»
«100500»
и т.д.

Впрочем, они и в хаскеле, и в руби, и в питоне работают.

Квайн должен явно распечатывать свой исходный код. Если выполнить ваш квайн, сохранив в файл, то ничего не выведется.
<?php
header("Content-type: text/plain; charset=UTF-8");
function hexToStr($hex)
{
$string='';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
$param = "|3c3f706870200d0a202020206865616465722822436f6e74656e742d747970653a20746578742f706c61696e3b20636861727365743d5554462d3822293b0d0a2020202066756e6374696f6e20686578546f5374722824686578290d0a202020207b0d0a202020202020202024737472696e673d27273b0d0a2020202020202020666f72202824693d303b202469203c207374726c656e2824686578292d313b2024692b3d32290d0a20202020202020207b0d0a20202020202020202020202024737472696e67202e3d206368722868657864656328246865785b24695d2e246865785b24692b315d29293b0d0a20202020202020207d0d0a202020202020202072657475726e2024737472696e673b0d0a202020207d0d0a2020202024706172616d203d20227c223b0d0a20202020246465636f646564203d20686578546f537472287375627374722824706172616d2c3129293b0d0a20202020666f72202824693d303b202469203c207374726c656e28246465636f646564293b202b2b2469290d0a202020207b0d0a096966286f726428246465636f6465645b24695d293d3d313234297b0d0a2020202020202020202020206563686f2024706172616d3b0d0a20202020202020207d656c73657b0d0a2020202020202020202020206563686f20246465636f6465645b24695d3b0d0a20202020202020207d0d0a202020207d0d0a3f3e";
$decoded = hexToStr(substr($param,1));
for ($i=0; $i < strlen($decoded); ++$i)
{
if(ord($decoded[$i])==124){
echo $param;
}else{
echo $decoded[$i];
}
}
?>
Код, печатающий сам себя. Может быть не самый короткий, но подобный способ работает на всех или почти всех языках программирования.

<?php 
    header("Content-type: text/plain; charset=UTF-8");
    function hexToStr($hex)
    {
        $string='';
        for ($i=0; $i < strlen($hex)-1; $i+=2)
        {
            $string .= chr(hexdec($hex[$i].$hex[$i+1]));
        }
        return $string;
    }
    $param = "|3c3f706870200d0a202020206865616465722822436f6e74656e742d747970653a20746578742f706c61696e3b20636861727365743d5554462d3822293b0d0a2020202066756e6374696f6e20686578546f5374722824686578290d0a202020207b0d0a202020202020202024737472696e673d27273b0d0a2020202020202020666f72202824693d303b202469203c207374726c656e2824686578292d313b2024692b3d32290d0a20202020202020207b0d0a20202020202020202020202024737472696e67202e3d206368722868657864656328246865785b24695d2e246865785b24692b315d29293b0d0a20202020202020207d0d0a202020202020202072657475726e2024737472696e673b0d0a202020207d0d0a2020202024706172616d203d20227c223b0d0a20202020246465636f646564203d20686578546f537472287375627374722824706172616d2c3129293b0d0a20202020666f72202824693d303b202469203c207374726c656e28246465636f646564293b202b2b2469290d0a202020207b0d0a096966286f726428246465636f6465645b24695d293d3d313234297b0d0a2020202020202020202020206563686f2024706172616d3b0d0a20202020202020207d656c73657b0d0a2020202020202020202020206563686f20246465636f6465645b24695d3b0d0a20202020202020207d0d0a202020207d0d0a3f3e";
    $decoded = hexToStr(substr($param,1));
    for ($i=0; $i < strlen($decoded); ++$i)
    {
	if(ord($decoded[$i])==124){
            echo $param;
        }else{
            echo $decoded[$i];
        }
    }
?>
На базовом С не требуется объявления прототипа функции (если она возвращает int). Поэтому stdio.h подключать не обязательно. И код можно сократить:

main(){char*s=«main(){char*s=%c%s%c;printf(s,34,s,34);}»;printf(s,34,s,34);}

76 символов.
Javascript #1 (вот прям по рецепту этой статьи!)
var a='"';var s="var a='';var s=;console.log(s.substr(0,7)+a+s.substr(7,8)+a+s+a+s.substr(15));";console.log(s.substr(0,7)+a+s.substr(7,8)+a+s+a+s.substr(15));


Javascript #2 (нашел у друга)
var o={q:'\'',b:'\\',s:'var o={q:_q_b_q_q,b:_q_b_b_q,s:_q_s_q};console.log(Object.keys(o).reduce(function(a,k){return a.split(_q__q+k).join(o[k])},o.s))'};console.log(Object.keys(o).reduce(function(a,k){return a.split('_'+k).join(o[k])},o.s))
Sign up to leave a comment.

Articles

Change theme settings