Haskell , 3 квина, 1119 байт
Quine 1, 51 байт
IOПечать анонимного действия напрямую на стандартный вывод.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Попробуйте онлайн!
Quine 2, 265 байт
Функция fпринимает фиктивный аргумент и возвращает строку.
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,90,52,82,89,52,51,51,94,84,24,24,39,34,34,106,95,102,110,0,94,50,89,0,90,52,82,82,82,106,95,102,110,0,48,24,24,39,35,106,95,102,110,0,40,24,24,39,37,37,84,24,24,45,37,37,84,24,24,90,84,50,94,52]
Попробуйте онлайн!
Quine 3, 803 байта
Все, что LANGUAGEидет после прагмы, является произвольной функцией, принимающей фиктивный аргумент и возвращающей строку.
{-#LANGUAGE CPP#-}(\q(_:_:_:_:_:_:_:_:z)y(#)_->(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z)'\''__TIME__(\(?)v k x->v$k?x)$ \(&)(%)v->v&'{'&'-'&'#'&'L'&'A'&'N'&'G'&'U'&'A'&'G'&'E'&' '&'C'&'P'&'P'&'#'&'-'&'}'&'('%'\\'&'q'&'('&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'z'&')'&'y'&'('&'#'&')'&'_'&'-'&'>'&'('&'y'&'('%'\\'&'k'&' '&'x'&'-'&'>'%'\''&'&'%'\''&':'&'q'&':'&'k'&':'&'q'&':'&'x'&')'&'#'&'y'&'('%'\\'&'k'&' '&'x'&'-'&'>'%'\''&'%'%'\''&':'&'q'&':'%'\''%'\\'%'\\'%'\''&':'&'k'&':'&'q'&':'&'x'&')'&'$'&'y'&'('&':'&')'&'#'&'y'&'('&':'&')'&'$'&' '%'\\'&'x'&'-'&'>'&'x'&')'&'z'&')'%'\''%'\\'%'\''%'\''&'_'&'_'&'T'&'I'&'M'&'E'&'_'&'_'&'('%'\\'&'('&'?'&')'&'v'&' '&'k'&' '&'x'&'-'&'>'&'v'&'$'&'k'&'?'&'x'&')'&'$'&' '%'\\'&'('&'&'&')'&'('&'%'&')'&'v'&'-'&'>'&'v'
Попробуйте онлайн!
Символы
Куайн 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Как это работает
Куайн 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 - это модифицированная версия моего недавнего Golf с ответом quine (с улучшениями от H.PWiz):
- Так как полные программы не нужны,
main=был удален.
<>и $были заменены их почти синонимами mappendи id.
Это освобождает жизненно важных персонажей =<>и полезного оператора $для других квинов.
Куайн 2
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,......]
В Quine 2 используются несколько аналогичные методы для программирования 2 в моем недавнем ответе « Взаимно исключающие квинусы» , но он приспособлен для непосредственного квинования себя и особенно для того, чтобы не использовать символьные литералы, которые необходимы для квин 3. Оба из них достигаются с помощью showфункции, который по счастливой случайности еще не использовал ни одного из своих персонажей.
В этой строке используются табуляции вместо пробелов, но я использовал пробелы ниже для удобства чтения.
gэто данные Quine, как список целых чисел в конце кода. Каждое число представляет символ из остальной части кода.
- Числа сдвинуты
9, так что вкладка есть 0. Это делает кодировку немного короче, позволяя строчным буквам для имен функций и переменных помещаться в 2 цифры.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c] является функцией для преобразования числа в символ (фактически строка из одного символа)
[[show 9!!0,show 1!!0..]!!6..] диапазон символов, начинающийся с символа табуляции, который индексируется с помощью !!c .
- Сам символ табуляции создается путем индексации в другом диапазоне
[show 9!!0,show 1!!0..], начиная с цифр '9'и'1' и прыжков вниз с шагом 8.
- Цифровые символы создаются путем индексации в
showстроке соответствующей цифры.
f c=[b=<<g]!!0++show g это основная функция. cэто фиктивный аргумент.
b=<<gиспользует =<<для преобразования каждого числа в gего символ. (Использование, =<<а не eg map, поэтому bнеобходимо обернуть его возвращенный символ в список.)
show gдает строковое представление gсписка России и ++объединяет строки.
- Потому что
=<<имеет более низкий приоритет, чем ++, некоторые скобки необходимы. Чтобы избежать использования ()(зарезервировано для Quine 3), [...]!!0индексирует в список с одним элементом.
Куайн 3
По замыслу других quines quine 3 по-прежнему имеет доступ к скобкам, лямбда-выражениям, символьным литералам и конструктору строки / списка :. Этого будет достаточно, чтобы построить функцию, которая предопределяет код на Куайна в строку.
К сожалению, все строчные гласные (кроме иногда y) были использованы, не оставляя полезных буквенно-цифровых встроенных функций. И []""ушли. Это не оставляет нормального способа создать пустую строку, чтобы начать притворяться, что код.
Тем не менее, почти все заглавные буквы все еще доступны, поэтому LANGUAGEпрагма для получения расширения языка возможна. Снова по счастливой случайности,CPP (включить препроцессор C) это единственное расширение языка, названное только заглавными буквами. И макросы CPP часто имеют заглавные имена.
Таким образом, чтобы получить необходимую пустую строку, квина включает CPP, использует __TIME__макрос для получения строковой константы формы "??:??:??"(удобно всегда иметь одинаковую длину) и сопоставления с образцом на ней.
{-#LANGUAGE CPP#-}(\q(_:_:_:_:_:_:_:_:z)y(#)_->(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z)'\''__TIME__(\(?)v k x->v$k?x)$ \(&)(%)v->v&'{'&'-'&......
После языковой прагмы квайн состоит из лямбда-выражения, связывающего свои параметры с этими четырьмя аргументами (оставляя последний фиктивный параметр _для последующего применения):
qпривязан к '\'', давая символ одинарной кавычки;
_:_:_:_:_:_:_:_:zпривязан __TIME__, то есть, как строка "??:??:??", создавая zпустую строку;
yпривязанный к (\(?)v k x->v$k?x)лямбда-комбинатору, используемому для преобразования данных о хине из левой ассоциированной ("foldl") в правую ассоциированную ("foldr") форму;
- Оператор
(#)привязан к \(&)(%)v->v&'{'&'-'&...самим данным по квине.
Данные по квине приводятся в форме церковного кодирования, лямбда-выражения с параметрами (&)(%)v.
- Применяя выражение к конкретным значениям для создания экземпляров
(&), (%)и vэта кодировка может использоваться либо для создания основного кода quine, либо для перестройки самого представления данных quine.
- По умолчанию правило фиксированности Хаскелла
&и %левых ассоциативных операторов стало внутри лямбды. Таким образом, параметры персонажа объединяются с начальными vслева.
- Для большинства персонажей
kесть соответствующий &'k'.
- Когда
kесть 'или \, которое необходимо экранировать внутри символьных литералов, вместо этого используется кодировка %'\k'.
Поскольку кодирование данных остается ассоциативным, а строки построены ассоциативным образом, y = (\(?)v k x->v$k?x)вводится комбинатор для устранения несоответствия.
y(...)предназначен для построения подходящих функций для использования в качестве данных (&)и (%)операторов quine
vявляется функцией от строк к строкам (для vпримера приводятся данные по квине ).
kявляется символом, xстрокой и ?оператором, который объединяет их в новую строку. (Для основного кода (?)=(:). Для фактического восстановления представления данных Quine это более сложно.)
- Таким образом,
y(?)v k = \x->v$k?xесть еще одна функция из строк в строки.
В качестве примера того, как это меняет ассоциативность, если (&)=y(:):
(v&k1&k2&k3) x
= (((v&k1)&k2)&k3) x
= y(:)(y(:)(y(:)v k1)k2)k3 x
= y(:)(y(:)v k1)k2 (k3:x)
= y(:)v k1 (k2:(k3:x))
= v (k1:(k2:(k3:x)))
= v (k1:k2:k3:x)
В более общем случае, когда (#)функция данных quine f1,f2является функциями, объединяющими символы со строками:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
применяя функцию данных quine с помощью (&)=y(f1)и (%)=y(f2), и это использует предписанные f1и f2для объединения символов данных quine с x, а затем передает полученную строку в v.
Тело основного лямбда-выражения объединяет все это:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:xдля символа, kпредшествующего &'k'строке x, в то время как '%':q:'\\':k:q:xprepends %'\k', которые являются их исходными формами данных Quine.
- Таким образом
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x, это правильные параметры для перестройки представления данных Quine, перед которым ставится финал z(пустая строка), а затем передается следующей функции.
y(:)#y(:) являются правильными параметрами для добавления основного кода квина в строку без других модификаций.
- В конце концов,
\x->xфункция ничего не делает с созданной формулой, которая возвращается.