Haskell , 3 Quines, 1119 Bytes
Quine 1, 51 Bytes
Eine anonyme IOAktion, die direkt auf stdout gedruckt wird.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Probieren Sie es online!
Quine 2, 265 Bytes
Die Funktion fakzeptiert ein Dummy-Argument und gibt eine Zeichenfolge zurück.
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]
Probieren Sie es online!
Quine 3, 803 Bytes
Alles nach dem LANGUAGEPragma ist eine beliebige Funktion, die ein Dummy-Argument verwendet und einen String zurückgibt.
{-#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'
Probieren Sie es online!
Zeichen
Quine 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Wie es funktioniert
Quine 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 ist eine modifizierte Version meines Golfs. Sie ist eine quine Antwort (mit Verbesserungen von H.PWiz):
- Da volle Programme nicht benötigt werden,
main=wurde entfernt.
<>und $wurden durch ihre Beinahe-Synonyme mappendund ersetzt id.
Dies macht die lebenswichtigen Charaktere =<>und den hilfreichen Operator $für die anderen Quines frei.
Quine 2
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,......]
Quine 2 verwendet ähnliche Methoden wie das Programm 2 meiner kürzlich erschienenen Antwort " Gegenseitig ausschließende Quines" , ist jedoch angepasst, um sich selbst direkt zu quinen und insbesondere die Verwendung von Zeichenliteralen zu vermeiden, die für Quine 3 benötigt werden. Beides wird mit Hilfe der showFunktion erreicht. was zum Glück noch keinen seiner Charaktere verwendet hat.
Diese Quine verwendet Tabulatoren anstelle von Leerzeichen, aber ich habe Leerzeichen zur besseren Lesbarkeit verwendet.
gist die Quine-Daten als eine Liste von ganzen Zahlen am Ende des Codes. Jede Zahl steht für ein Zeichen aus dem Rest des Codes.
- Die Nummern werden um verschoben
9, so dass die Registerkarte ist 0. Dadurch wird die Codierung etwas kürzer, da die Kleinbuchstaben für die Funktions- und Variablennamen zweistellig sind.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c] ist eine Funktion, um eine Zahl in ein Zeichen umzuwandeln (eigentlich eine Zeichenkette aus einem Zeichen).
[[show 9!!0,show 1!!0..]!!6..]ist ein Zeichenbereich, der mit einem Tabulatorzeichen beginnt, das mit indiziert wird !!c.
- Das Tabulatorzeichen selbst wird durch Indizieren in einen anderen Bereich erzeugt
[show 9!!0,show 1!!0..], wobei mit den Ziffern begonnen wird '9'und '1'in Schritten von 8 nach unten gesprungen wird.
- Die Ziffernzeichen werden durch Indizieren in die
showZeichenfolge der entsprechenden Ziffer erzeugt.
f c=[b=<<g]!!0++show gist die Hauptfunktion. cist ein Scheinargument.
b=<<gverwendet =<<, um jede Zahl in gihr Zeichen umzuwandeln . (Die Verwendung von =<<anstelle von z. B. mapist, warum bdas zurückgegebene Zeichen in eine Liste eingeschlossen werden muss.)
show gGibt die Zeichenfolgendarstellung der gListe von an und ++verkettet die Zeichenfolgen.
- Da es
=<<eine niedrigere Priorität als hat ++, ist eine gewisse Belichtungsreihe erforderlich. Indiziert eine Liste mit einem Element, um die Verwendung von ()(für Quine 3 reserviert) zu vermeiden [...]!!0.
Quine 3
Aufgrund des Designs der anderen Quines hat Quine 3 weiterhin Zugriff auf Klammern, Lambda-Ausdrücke, Zeichenliterale und den String / List-Konstruktor :. Dies reicht aus, um eine Funktion zu erstellen, die den Code der Quine einer Zeichenfolge voranstellt .
Leider wurden alle Vokale in Kleinbuchstaben (außer manchmal y) verwendet, sodass keine nützlichen alphanumerischen Funktionen vorhanden waren. Auch []""sind verschwunden. Diese Blätter keine normale Art und Weise eine leere Zeichenfolge zu bauen zu beginnen vorgibt , um den Code zu.
Fast alle Großbuchstaben sind jedoch noch verfügbar, sodass ein LANGUAGEPragma für eine Spracherweiterung möglich ist. Auch hier ist CPP(enable C preprocessor) die einzige Spracherweiterung, die nur mit Großbuchstaben benannt wird. CPP-Makros haben häufig Namen in Großbuchstaben.
Um den wesentlichen leeren String zu erhalten, aktiviert das quine CPP, verwendet das __TIME__Makro, um eine String-Konstante des Formulars zu erhalten "??:??:??"(die bequemerweise garantiert immer die gleiche Länge hat) und Musterübereinstimmungen darauf.
{-#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&'{'&'-'&......
Nach dem Sprach-Pragma besteht das Quine aus einem Lambda-Ausdruck, der seine Parameter an diese vier Argumente bindet (wobei ein letzter Dummy-Parameter _für die spätere Anwendung übrig bleibt ):
qgebunden an '\'', ein einfaches Anführungszeichen gebend;
_:_:_:_:_:_:_:_:zgebunden an __TIME__, auch bekannt als eine Zeichenkette "??:??:??", wodurch zeine leere Zeichenkette entsteht;
ygebunden an (\(?)v k x->v$k?x)einen Lambda-Kombinator, der verwendet wird, um das Konvertieren der Quine-Daten von der links zugeordneten ("foldl") in die rechts zugeordnete ("foldr") Form zu unterstützen;
- Der Bediener ist daran
(#)gebunden \(&)(%)v->v&'{'&'-'&..., die Daten quine selbst.
Die Quine-Daten werden in Form einer Church-Codierung angegeben, einem Lambda-Ausdruck mit Parametern (&)(%)v.
- Durch Anwenden des Ausdrucks auf bestimmte Werte zu instanziieren
(&), (%)und vkann diese Codierung entweder verwendet werden , um den Kerncode des quine zu bauen oder die Datendarstellung quine selbst umzubauen.
- Nach Haskells Standard-Fixitätsregel werden
&und %assoziative Operatoren im Lambda belassen. Somit werden die Zeichenparameter mit dem Anfangsbuchstaben vvon links beginnend kombiniert .
- Für die meisten Zeichen
kgibt es eine entsprechende &'k'.
- Wenn
kist 'oder \, die innerhalb Zeichenliterale werden müssen entkommen, ist die Codierung statt %'\k'.
Da die Datencodierung linksassoziativ ist, Zeichenfolgen jedoch rechtsassoziativ aufgebaut sind, wird der Kombinator y = (\(?)v k x->v$k?x)eingeführt, um die Nichtübereinstimmung zu überbrücken.
y(...)soll geeignete Funktionen für die Verwendung als Quine-Daten (&)und (%)Operatoren erstellen .
vist eine Funktion von Zeichenkette zu Zeichenkette (die beabsichtigten vQuinedaten sind Beispiele).
kist ein Zeichen, xeine Zeichenfolge und ?ein Operator, der sie zu einer neuen Zeichenfolge kombiniert. (Für den Kerncode (?)=(:). Um die quine-Datendarstellung tatsächlich zu rekonstruieren, ist es komplizierter.)
- So
y(?)v k = \x->v$k?xist eine andere Funktion von Zeichenketten zu Zeichenketten.
Als Beispiel dafür, wie dies die Assoziativität ändert, wenn (&)=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)
Im Allgemeinen gilt: Wann (#)ist die Quine-Datenfunktion und wann f1,f2sind Funktionen, die Zeichen mit Zeichenfolgen kombinieren:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
Anwenden der Quine-Datenfunktion mit (&)=y(f1)und (%)=y(f2), und dies verwendet die vorgeschriebenen f1und f2, um die Zeichen der Quine-Daten mit zu kombinieren x, und übergibt dann den resultierenden String an v.
Der Hauptteil des Lambda-Ausdrucks fügt dies zusammen:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:xEin Zeichen kwird &'k'der Zeichenfolge vorangestellt x, während die ursprünglichen Quine-Datenformen '%':q:'\\':k:q:xvorangestellt %'\k'werden.
- Somit
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:xsind die richtigen Parameter für die Neuerstellung der Quine-Datendarstellung vorhanden, die dem final z(der leeren Zeichenfolge) vorangestellt und dann an die folgende Funktion übergeben werden.
y(:)#y(:) sind die richtigen Parameter, um den Kerncode des Quines ohne weitere Modifikation einem String voran zu stellen.
- Schließlich wird das
\x->xbekommt nichts mit dem konstruierten quine zu tun, die zurückgegeben wird.