Haskell , 3 quines, 1119 octets
Quine 1, 51 octets
Une IO
action anonyme imprimant directement sur stdout.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Essayez-le en ligne!
Quine 2, 265 octets
La fonction f
prend un argument fictif et renvoie une chaîne.
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]
Essayez-le en ligne!
Quine 3, 803 octets
Tout ce qui suit le LANGUAGE
pragma est une fonction quelconque qui prend un argument fictif et renvoie une chaîne.
{-#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'
Essayez-le en ligne!
Personnages
Quine 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Comment ça marche
Quine 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 est une version modifiée de mon récent Golf you a quine answer (avec des améliorations de H.PWiz):
- Étant donné que les programmes complets ne sont pas nécessaires,
main=
a été supprimé.
<>
et $
ont été remplacés par leurs quasi-synonymes mappend
et id
.
Cela libère les caractères vitaux =<>
et l'opérateur utile $
pour les autres 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 utilise des méthodes quelque peu similaires pour programmer 2 de ma récente réponse Mutuellement Exclusif Quines , mais adapté pour se quine directement et surtout pour éviter d'utiliser des littéraux de caractères, qui sont nécessaires pour la quine 3. Ces deux sont obtenus à l'aide de la show
fonction, qui, par pure chance, n'a encore utilisé aucun de ses personnages.
Cette quine utilise des tabulations au lieu d'espaces, mais j'ai utilisé les espaces ci-dessous pour plus de lisibilité.
g
correspond aux données de quine, sous la forme d'une liste d'entiers à la fin du code. Chaque numéro représente un caractère du reste du code.
- Les nombres sont décalés de
9
, donc cet onglet l'est 0
. Cela rend l'encodage un peu plus court en permettant aux lettres minuscules de la fonction et aux noms de variables de tenir sur 2 chiffres.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c]
est une fonction pour convertir un nombre en caractère (en fait une chaîne à un caractère).
[[show 9!!0,show 1!!0..]!!6..]
est une plage de caractères commençant par un caractère de tabulation, qui est indexé dans avec !!c
.
- Le caractère de tabulation est lui - même produit par l' indexation dans une autre plage
[show 9!!0,show 1!!0..]
, en commençant par les caractères numériques '9'
et '1'
et sautant par pas de huit.
- Les caractères numériques sont produits par indexation dans la
show
chaîne du chiffre correspondant.
f c=[b=<<g]!!0++show g
est la fonction principale. c
est un argument factice.
b=<<g
utilise =<<
pour convertir chaque nombre en g
son caractère. (L'utilisation de =<<
plutôt que par exemple map
est la raison b
pour laquelle il faut envelopper son caractère retourné dans une liste.)
show g
donne la représentation sous forme de chaîne de g
la liste de et ++
concatène les chaînes.
- Parce qu'il
=<<
a une priorité inférieure à ++
, un certain bracketing est nécessaire. Pour éviter d'utiliser ()
(réservé au quine 3), [...]!!0
indexe dans une liste avec un élément.
Quine 3
De par la conception des autres quines, quine 3 a toujours accès aux parenthèses, aux expressions lambda, aux littéraux de caractères et au constructeur de chaîne / liste :
. Ce sera suffisant pour construire une fonction qui ajoute le code du quine à une chaîne.
Malheureusement, toutes les voyelles minuscules (sauf parfois y
) ont été utilisées, ne laissant aucune fonction intégrée alphanumérique utile. Sont également []""
partis. Cela ne laisse aucun moyen normal de construire une chaîne vide pour commencer à faire semblant le code.
Cependant, presque toutes les lettres majuscules sont toujours disponibles, donc un LANGUAGE
pragma pour obtenir une extension de langue est possible. Encore une fois, par pure chance, CPP
(activer le préprocesseur C) est la seule extension de langage nommée avec uniquement des lettres majuscules. Et les macros CPP ont souvent des noms en majuscules.
Ainsi, pour obtenir la chaîne vide essentielle, le quine permet CPP
, utilise la __TIME__
macro pour obtenir une constante de chaîne de la forme "??:??:??"
(il est commodément garanti de toujours avoir la même longueur), et le modèle correspond.
{-#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&'{'&'-'&......
Après le pragma du langage, le quine consiste en une expression lambda liant ses paramètres à ces quatre arguments (laissant un paramètre factice final _
à appliquer plus tard):
q
lié à '\''
, donnant un caractère de guillemet simple;
_:_:_:_:_:_:_:_:z
lié à __TIME__
, alias une chaîne similaire "??:??:??"
, créant ainsi z
une chaîne vide;
y
lié à (\(?)v k x->v$k?x)
, un combinateur lambda utilisé pour aider à convertir les données de quine de la forme associée à gauche ("foldl") à la forme associée à droite ("foldr");
- L'opérateur
(#)
lié à \(&)(%)v->v&'{'&'-'&...
, les données quine lui-même.
Les données de quine sont données sous une forme de codage Church, une expression lambda avec des paramètres (&)(%)v
.
- En appliquant l'expression à des valeurs particulières pour instancier
(&)
, (%)
et v
, cet encodage peut être utilisé soit pour construire le code principal du quine, soit pour reconstruire la représentation des données du quine elle-même.
- Par la règle de fixité par défaut de Haskell,
&
et %
devenez des opérateurs associatifs gauches à l'intérieur du lambda. Ainsi, les paramètres des caractères se combinent avec l'initiale en v
partant de la gauche.
- Pour la plupart des personnages
k
, il existe un correspondant &'k'
.
- Quand
k
est '
ou \
, qui doit être échappé à l'intérieur des littéraux de caractères, le codage est à la place %'\k'
.
Étant donné que le codage des données est associatif à gauche, mais que les chaînes sont construites de manière associative à droite, le combinateur y = (\(?)v k x->v$k?x)
est introduit pour combler le décalage.
y(...)
est destiné à construire des fonctions appropriées à utiliser comme données (&)
et (%)
opérateurs de quine .
v
est une fonction de chaînes en chaînes (les données prévues v
sont des exemples).
k
est un caractère, x
une chaîne et ?
un opérateur qui les combine en une nouvelle chaîne. (Pour le code principal,. (?)=(:)
Pour reconstruire réellement la représentation des données quine, c'est plus compliqué.)
- C'est donc
y(?)v k = \x->v$k?x
une autre fonction de chaînes en chaînes.
Comme exemple de la façon dont cela change l'associativité, si (&)=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)
Plus généralement, quand (#)
est la fonction de données quine et f1,f2
sont des fonctions combinant des caractères avec des chaînes:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
appliquer la fonction de données de quine avec (&)=y(f1)
et (%)=y(f2)
, et cela utilise les éléments prescrits f1
et f2
pour combiner les caractères des données de quine avec x
, puis passe la chaîne résultante à v
.
Le corps de l'expression lambda principale met tout cela ensemble:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:x
pour un caractère k
précède &'k'
la chaîne x
, tandis que les '%':q:'\\':k:q:x
préfixes %'\k'
, qui sont leurs formes de données de quine d'origine.
- Ce
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
sont donc les bons paramètres pour reconstruire la représentation des données de quine, ajoutés à la finale z
(la chaîne vide), puis passés à la fonction suivante.
y(:)#y(:)
sont les bons paramètres pour ajouter le code de base du quine à une chaîne, sans autre modification.
- Enfin, le
\x->x
fait de ne rien faire avec le quine construit, qui est retourné.