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:x
prepends %'\k'
, которые являются их исходными формами данных Quine.
- Таким образом
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
, это правильные параметры для перестройки представления данных Quine, перед которым ставится финал z
(пустая строка), а затем передается следующей функции.
y(:)#y(:)
являются правильными параметрами для добавления основного кода квина в строку без других модификаций.
- В конце концов,
\x->x
функция ничего не делает с созданной формулой, которая возвращается.