Haskell , 3 Quines, 1119 Bytes
Quine 1, 51 Bytes
Eine anonyme IO
Aktion, die direkt auf stdout gedruckt wird.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Probieren Sie es online!
Quine 2, 265 Bytes
Die Funktion f
akzeptiert 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 LANGUAGE
Pragma 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 mappend
und 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 show
Funktion 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.
g
ist 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
show
Zeichenfolge der entsprechenden Ziffer erzeugt.
f c=[b=<<g]!!0++show g
ist die Hauptfunktion. c
ist ein Scheinargument.
b=<<g
verwendet =<<
, um jede Zahl in g
ihr Zeichen umzuwandeln . (Die Verwendung von =<<
anstelle von z. B. map
ist, warum b
das zurückgegebene Zeichen in eine Liste eingeschlossen werden muss.)
show g
Gibt die Zeichenfolgendarstellung der g
Liste 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 LANGUAGE
Pragma 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 ):
q
gebunden an '\''
, ein einfaches Anführungszeichen gebend;
_:_:_:_:_:_:_:_:z
gebunden an __TIME__
, auch bekannt als eine Zeichenkette "??:??:??"
, wodurch z
eine leere Zeichenkette entsteht;
y
gebunden 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 v
kann 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 v
von links beginnend kombiniert .
- Für die meisten Zeichen
k
gibt es eine entsprechende &'k'
.
- Wenn
k
ist '
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 .
v
ist eine Funktion von Zeichenkette zu Zeichenkette (die beabsichtigten v
Quinedaten sind Beispiele).
k
ist ein Zeichen, x
eine 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?x
ist 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,f2
sind 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 f1
und 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:x
Ein Zeichen k
wird &'k'
der Zeichenfolge vorangestellt x
, während die ursprünglichen Quine-Datenformen '%':q:'\\':k:q:x
vorangestellt %'\k'
werden.
- Somit
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
sind 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->x
bekommt nichts mit dem konstruierten quine zu tun, die zurückgegeben wird.