Haskell , 3 piny, 1119 bajtów
Quine 1, 51 bajtów
Anonimowa IOakcja drukowana bezpośrednio na standardowe wyjście.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Wypróbuj online!
Quine 2, 265 bajtów
Funkcja fprzyjmuje fikcyjny argument i zwraca ciąg znaków.
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]
Wypróbuj online!
Quine 3, 803 bajtów
Wszystko po LANGUAGEpragmie jest anymalną funkcją, przyjmującą fikcyjny argument i zwracającą ciąg znaków.
{-#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'
Wypróbuj online!
Postacie
Quine 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Jak to działa
Quine 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 to zmodyfikowana wersja mojego ostatniego Golfa, odpowiedź quine (z ulepszeniami H.PWiz):
- Ponieważ pełne programy nie są potrzebne,
main=został usunięty.
<>i $zostały zastąpione ich prawie synonimami mappendi id.
Uwalnia to ważne postacie =<>i pomocnego operatora $dla innych quines.
Quine 2
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,......]
Quine 2 używa nieco podobnych metod do programowania 2 moich ostatnich wzajemnie wykluczających się Quines , ale dostosowano ją do bezpośredniego quinowania się, a zwłaszcza w celu uniknięcia używania literałów znaków, które są potrzebne dla quine 3. Oba te sposoby są osiągane za pomocą showfunkcji, na szczęście nie wykorzystano jeszcze żadnej z jego postaci.
Quine używa tabulatorów zamiast spacji, ale dla czytelności użyłem spacji poniżej.
gto dane quine, jako lista liczb całkowitych na końcu kodu. Każda liczba reprezentuje znak z reszty kodu.
- Liczby są przesuwane
9, tak aby tabulator był 0. To sprawia, że kodowanie jest nieco krótsze, ponieważ małe litery w nazwach funkcji i zmiennych mogą zmieścić się w 2 cyfrach.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c] to funkcja służąca do konwersji liczby na znak (w rzeczywistości ciąg jednoznakowy).
[[show 9!!0,show 1!!0..]!!6..] to zakres znaków rozpoczynający się od znaku tabulacji, do którego indeksuje się !!c .
- Znak tabulacji jest wytwarzany przez indeksowanie do innego zakresu
[show 9!!0,show 1!!0..], zaczynając od cyfr '9'i'1' i skoki w krokach 8.
- Znaki cyfr są tworzone przez indeksowanie w
showciągu odpowiedniej cyfry.
f c=[b=<<g]!!0++show gjest główną funkcją. cjest fałszywym argumentem.
b=<<gsłuży =<<do konwertowania każdej liczby gna jej znak. (Użycie =<<zamiast np mapDlatego bpotrzeby owinąć swój charakter zwrócony w liście).
show gdaje ciąg znaków reprezentujący glistę, oraz++ łączy ciągi znaków.
- Ponieważ
=<<ma niższy priorytet niż ++, potrzebne jest trochę braketingu. Aby uniknąć używania ()(zarezerwowane dla quine 3), [...]!!0indeksuje do listy z jednym elementem.
Quine 3
Zgodnie z projektem innych quinesów, quine 3 nadal ma dostęp do nawiasów, wyrażeń lambda, literałów znaków i konstruktora ciągów / list :. To wystarczy, aby skonstruować funkcję, która będzie kontynuowana Kodeksu Quine'a na sznurku.
Niestety, wszystkie samogłoski pisane małymi literami (z wyjątkiem czasami y) zostały użyte, nie pozostawiając żadnych przydatnych wbudowanych funkcji alfanumerycznych. Też []""już nie ma. Nie pozostawia to normalnego sposobu na zbudowanie pustego ciągu, aby rozpocząć udawanie kodu.
Jednak prawie wszystkie wielkie litery są nadal dostępne, więc istnieje LANGUAGEmożliwość uzyskania rozszerzenia języka. Ponownie, dzięki szczęściu, CPP(włącz preprocesor C) jest jedynym rozszerzeniem językowym o nazwie zawierającym tylko wielkie litery. Makra CPP często mają wielkie litery.
Aby uzyskać niezbędny pusty ciąg, quine włącza CPP, używa __TIME__makra, aby uzyskać stałą ciągu formy "??:??:??"(wygodnie jest mieć zawsze tę samą długość) i dopasować wzorzec na nim.
{-#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&'{'&'-'&......
Po pragmie języka quine składa się z wyrażenia lambda wiążącego swoje parametry z tymi czterema argumentami (pozostawiając końcowy parametr pozorny _do zastosowania później):
qzwiązany '\'', dając pojedynczy znak cudzysłowu;
_:_:_:_:_:_:_:_:zzwiązany __TIME__, podobnie jak łańcuch "??:??:??", tworząc zpusty łańcuch;
yzwiązany z (\(?)v k x->v$k?x)kombinatorem lambda używanym do konwersji danych quine z postaci powiązanej od lewej („foldl”) do postaci powiązanej z prawą („foldr”);
- Operator
(#)zobowiązał się do \(&)(%)v->v&'{'&'-'&...samych danych quine.
Dane z quine są podane w formie kodowania Churcha, wyrażenia lambda z parametrami (&)(%)v.
- Przez zastosowanie wyrażenia do określonych wartości do utworzenia wystąpienia
(&), (%)orazv to kodowanie może być użyte albo do zbudowania podstawowego kodu quine, albo do przebudowania samej reprezentacji danych quine.
- Domyślnie reguła stałości Haskell jest,
&i %stać lewo operatorom asocjacyjnych wewnątrz lambda. W ten sposób parametry postaci łączą się z początkowym, vzaczynając od lewej.
- W przypadku większości znaków
kistnieje odpowiednik &'k'.
- Gdy
kjest 'lub \, które muszą być poprzedzone znakami literowymi, kodowanie odbywa się zamiast tego %'\k'.
Ponieważ kodowanie danych jest asocjacyjne, ale łańcuchy są budowane we właściwy sposób asocjatywny, wprowadzono kombinator w y = (\(?)v k x->v$k?x)celu wyeliminowania niedopasowania.
y(...)ma na celu zbudowanie odpowiednich funkcji do wykorzystania jako danych (&)i (%)operatorów quine .
vjest funkcją od ciągów do ciągów (dane quine vsą przykładami).
kto znak, xciąg i ?operator, który łączy je w nowy ciąg. (W przypadku kodu podstawowego (?)=(:). Dla faktycznej rekonstrukcji reprezentacji danych quine jest to bardziej skomplikowane.)
- Zatem
y(?)v k = \x->v$k?xjest inną funkcją od ciągów do ciągów.
Jako przykład tego, jak to zmienia skojarzenie, jeśli (&)=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)
Mówiąc bardziej ogólnie, kiedy (#)jest to funkcja danych quine i f1,f2są to funkcje łączące znaki z łańcuchami:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
zastosowanie funkcji danych quine za pomocą (&)=y(f1)i (%)=y(f2), i to wykorzystuje przepisane f1i f2do łączenia znaków danych quine z x, a następnie przekazuje wynikowy ciąg do v.
Ciało głównego wyrażenia lambda łączy to wszystko:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:xponieważ znak kpoprzedza &'k'ciąg znaków x, podczas gdy '%':q:'\\':k:q:xpoprzedza %'\k', które są ich oryginalnymi formami danych quine.
- Zatem
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:xodpowiednie parametry do przebudowania reprezentacji danych quine, dołączone do finałuz (pusty ciąg), a następnie przekazane do następującej funkcji.
y(:)#y(:) są właściwymi parametrami do dodania kodu podstawowego quine do łańcucha, bez innych modyfikacji.
- Wreszcie
\x->xnie można nic zrobić ze skonstruowanym quine, który jest zwracany.