Haskell , 3 piny, 1119 bajtów
Quine 1, 51 bajtów
Anonimowa IO
akcja drukowana bezpośrednio na standardowe wyjście.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Wypróbuj online!
Quine 2, 265 bajtów
Funkcja f
przyjmuje 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 LANGUAGE
pragmie 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 mappend
i 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ą show
funkcji, 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.
g
to 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
show
ciągu odpowiedniej cyfry.
f c=[b=<<g]!!0++show g
jest główną funkcją. c
jest fałszywym argumentem.
b=<<g
służy =<<
do konwertowania każdej liczby g
na jej znak. (Użycie =<<
zamiast np map
Dlatego b
potrzeby owinąć swój charakter zwrócony w liście).
show g
daje ciąg znaków reprezentujący g
listę, oraz++
łączy ciągi znaków.
- Ponieważ
=<<
ma niższy priorytet niż ++
, potrzebne jest trochę braketingu. Aby uniknąć używania ()
(zarezerwowane dla quine 3), [...]!!0
indeksuje 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 LANGUAGE
moż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):
q
związany '\''
, dając pojedynczy znak cudzysłowu;
_:_:_:_:_:_:_:_:z
związany __TIME__
, podobnie jak łańcuch "??:??:??"
, tworząc z
pusty łańcuch;
y
zwią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, v
zaczynając od lewej.
- W przypadku większości znaków
k
istnieje odpowiednik &'k'
.
- Gdy
k
jest '
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 .
v
jest funkcją od ciągów do ciągów (dane quine v
są przykładami).
k
to znak, x
cią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?x
jest 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,f2
są 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 f1
i f2
do łą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:x
ponieważ znak k
poprzedza &'k'
ciąg znaków x
, podczas gdy '%':q:'\\':k:q:x
poprzedza %'\k'
, które są ich oryginalnymi formami danych quine.
- Zatem
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
odpowiednie 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->x
nie można nic zrobić ze skonstruowanym quine, który jest zwracany.