Haskell , 3 quines, 1119 байт
Quine 1, 51 байт
Анонімний IOдрук дій безпосередньо до stdout.
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
Квінт 2:
!+,.0123456789;<=[]bcfghosw
Квінт 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Як це працює
Квінка 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 - це модифікована версія мого недавнього Гольфу, вам відповідь (з удосконаленнями 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 моєї останньої взаємовиключної відповіді Quines , але пристосовану для прямого квіта , а особливо для уникнення використання літеральних символів, необхідних для quine 3. Обидва ці функції досягаються за допомогою showфункції, котрий за великою долею ще не використовував жодного свого персонажа.
Цей квінт використовує вкладки замість пробілів, але я використовував пробіли нижче для читання.
g- це дані quine, як список цілих чисел в кінці коду. Кожне число представляє символ із решти коду.
- Цифри зміщуються на
9, так що ця вкладка є 0. Це робить кодування трохи коротшим, дозволяючи маленьким літерам для функцій та імен змінних розміщуватися у двох цифрах.
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його символ. (Використання, =<<а не напр. map, Тому bпотрібно загорнути його повернутий символ у список.)
show gдає рядкове представлення gсписку 's і ++об'єднує рядки.
- Оскільки
=<<має нижчий пріоритет, ніж ++потрібне деяке дужки. Щоб уникнути використання ()(зарезервовано для quine 3), [...]!!0індексується до списку з одним елементом.
Квінт 3
Конструюючи інші лайки, quine 3 все ще має доступ до круглих дужок, лямбда-виразів, буквених символів та конструктора рядків / списку :. Цього буде достатньо для побудови функції, яка передує код quine до рядка.
На жаль, всі голосні голосні yбукви (крім інколи ) були використані, не залишаючи корисних буквено-цифрових вбудованих функцій. Також []""пішли. Це не залишає нормального способу побудувати порожній рядок, щоб почати робити вигляд на код.
Однак майже всі великі літери все ще доступні, тому можлива LANGUAGEпрагма отримати розширення мови. Знову ж таки з великою долею CPP(увімкніть препроцесор C) - це єдине розширення мови, назване лише великими літерами. А CPP макроси часто мають великі імена.
Таким чином, щоб отримати істотну порожню рядок, quine enable 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&'{'&'-'&......
Після мовної прагми quine складається з лямбда-виразу, що зв'язує свої параметри з цими чотирма аргументами (залишаючи остаточний параметр манекена, _який слід застосувати пізніше):
qприв’язаний до '\''надання символу єдиної цитати;
_:_:_:_:_:_:_:_:zприв’язаний до __TIME__aka, як строка як "??:??:??", таким чином, роблячи zпорожню рядок;
yприв’язаний до (\(?)v k x->v$k?x)лямбда-комбінатора, який використовується для перетворення даних квіни з асоційованої зліва ("foldl") у форму, пов'язану з правою ("foldr");
- Оператор,
(#)пов'язаний \(&)(%)v->v&'{'&'-'&...з самими даними quine.
Дані quine подаються у вигляді кодування Церкви, лямбда-виразу з параметрами (&)(%)v.
- Застосовуючи вираз до конкретних значень для екземпляра
(&), (%)і vце кодування можна використовувати або для побудови основного коду quine, або для відновлення самого представлення даних quine.
- За правилом виправлення Haskell за замовчуванням,
&і %стають лівими асоціативними операторами всередині лямбда. Таким чином, параметри символів поєднуються з початковим vпочатком зліва.
- Для більшості персонажів
kє відповідне &'k'.
- Коли
kє 'або \, які потрібно уникнути всередині літературних символів, замість цього відбувається кодування %'\k'.
Оскільки кодування даних є лівим асоціативним, але рядки побудовані у правій асоціативній формі, комбінатор y = (\(?)v k x->v$k?x)вводиться для усунення невідповідності.
y(...)призначений для побудови відповідних функцій для використання в якості даних quine (&)та (%)операторів.
v- це функція від рядків до рядків ( vприклади даних, призначених для quine, є прикладами).
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вперед %'\k'- на їх початкові форми даних quine .
- Таким чином
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x, правильні параметри для відновлення подання даних quine, попередньо висунуті до остаточного z(порожня рядок), а потім передані наступній функції.
y(:)#y(:) - це правильні параметри для додавання основного коду quine до рядка без інших змін.
- Нарешті,
\x->xзмушений нічого не робити з побудованою quine, яка повертається.