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, яка повертається.