Haskell , 3 quines, 1119 bytes
Quine 1, 51 bytes
Una IO
acción anónima que se imprime directamente en stdout.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Pruébalo en línea!
Quine 2, 265 bytes
La función f
toma un argumento ficticio y devuelve una cadena.
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]
Pruébalo en línea!
Quine 3, 803 bytes
Todo lo que LANGUAGE
sigue al pragma es una función cualquiera que toma un argumento ficticio y devuelve una cadena.
{-#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'
Pruébalo en línea!
Caracteres
Quine 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Cómo funciona
Quine 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 es una versión modificada de mi reciente Golf, una respuesta quine (con mejoras de H.PWiz):
- Como no se necesitan programas completos,
main=
se ha eliminado.
<>
y $
han sido reemplazados por sus casi sinónimos mappend
y id
.
Esto libera los caracteres vitales =<>
y el operador útil $
para las otras 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 utiliza métodos algo similares para programar 2 de mi respuesta reciente de Quines mutuamente excluyentes , pero adaptado para quine directamente y especialmente para evitar el uso de literales de caracteres, que son necesarios para quine 3. Ambos se logran con la ayuda de la show
función, que por pura suerte aún no se ha utilizado ninguno de sus personajes.
Esta línea utiliza pestañas en lugar de espacios, pero he usado los espacios a continuación para facilitar la lectura.
g
son los datos de quine, como una lista de enteros al final del código. Cada número representa un carácter del resto del código.
- Los números se desplazan por
9
, de modo que la pestaña es 0
. Esto hace que la codificación sea un poco más corta al permitir que las letras minúsculas para la función y los nombres de las variables quepan en 2 dígitos.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c]
es una función para convertir un número en un carácter (en realidad, una cadena de un carácter).
[[show 9!!0,show 1!!0..]!!6..]
es un rango de caracteres que comienza con un carácter de tabulación, que se indexa con !!c
.
- El propio carácter de tabulación se produce mediante la indexación en otra gama
[show 9!!0,show 1!!0..]
, a partir de los caracteres de dígitos '9'
y '1'
y saltando hacia abajo en pasos de 8.
- Los caracteres del dígito se producen indexando en la
show
cadena del dígito correspondiente.
f c=[b=<<g]!!0++show g
Es la función principal. c
Es un argumento ficticio.
b=<<g
utiliza =<<
para convertir cada número en g
su carácter. (El uso de, en =<<
lugar de, por ejemplo, map
es el motivo por el que b
debe incluir su carácter devuelto en una lista).
show g
da la representación de cadena de g
la lista de 's, y ++
concatena las cadenas.
- Debido a que
=<<
tiene una precedencia más baja que ++
, se necesita un paréntesis. Para evitar el uso ()
(reservado para quine 3), [...]!!0
indexa en una lista con un elemento.
Quine 3
Por diseño de los otros quines, el quine 3 todavía tiene acceso a paréntesis, expresiones lambda, literales de caracteres y el constructor de cadenas / listas :
. Esto será suficiente para construir una función que anteponga el código del quine a una cadena.
Desafortunadamente, y
se han usado todas las vocales en minúsculas (excepto algunas veces ), sin dejar funciones alfanuméricas incorporadas útiles. También []""
se han ido. Esto no deja una forma normal de construir una cadena vacía para comenzar a simular el código.
Sin embargo, casi todas las letras mayúsculas todavía están disponibles, por lo que LANGUAGE
es posible un pragma para obtener una extensión de idioma. Nuevamente, por pura suerte, CPP
(habilitar el preprocesador C) es la única extensión de lenguaje nombrada con solo letras mayúsculas. Y las macros CPP a menudo tienen nombres en mayúscula.
Entonces, para obtener la cadena vacía esencial, la función quine habilita CPP
, usa la __TIME__
macro para obtener una cadena constante de la forma "??:??:??"
(convenientemente garantizada que siempre tenga la misma longitud), y coincide con el patrón.
{-#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&'{'&'-'&......
Después del pragma del lenguaje, la quine consiste en una expresión lambda que une sus parámetros a estos cuatro argumentos (dejando un parámetro ficticio final _
que se aplicará más adelante):
q
obligado a '\''
, dando una comilla simple;
_:_:_:_:_:_:_:_:z
unido a __TIME__
, también conocido como una cadena "??:??:??"
, haciendo así z
una cadena vacía;
y
enlazado a (\(?)v k x->v$k?x)
, un combinador lambda usado para ayudar a convertir los datos de quine del formulario asociado a la izquierda ("foldl") al formulario asociado a la derecha ("foldr");
- El operador
(#)
vinculado a \(&)(%)v->v&'{'&'-'&...
los datos de quine en sí.
Los datos de quine se dan en forma de codificación de Church, una expresión lambda con parámetros (&)(%)v
.
- Al aplicar la expresión a valores particulares para crear instancias
(&)
, (%)
y v
, esta codificación se puede usar para construir el código central de la quine o para reconstruir la representación de datos de quine en sí.
- Por la regla de fijación predeterminada de Haskell,
&
y se %
convierten en operadores asociativos a la izquierda dentro de la lambda. Por lo tanto, los parámetros de caracteres se combinan con el v
inicio inicial desde la izquierda.
- Para la mayoría de los personajes
k
, hay un correspondiente &'k'
.
- Cuando
k
is '
o \
, que deben escaparse dentro de los literales de caracteres, la codificación es en su lugar %'\k'
.
Dado que la codificación de datos se deja asociativa, pero las cadenas se construyen de manera asociativa derecha, el combinador y = (\(?)v k x->v$k?x)
se introduce para cerrar la falta de coincidencia.
y(...)
está destinado a construir funciones adecuadas para usar como datos (&)
y (%)
operadores de quine .
v
es una función de cadenas a cadenas (los datos de quine v
son ejemplos).
k
es un personaje, x
una cadena y ?
un operador que los combina en una nueva cadena. (Para el código central,. (?)=(:)
Para reconstruir realmente la representación de datos de quine, es más complicado).
- Por
y(?)v k = \x->v$k?x
lo tanto, es otra función de cadenas a cadenas.
Como ejemplo de cómo esto cambia la asociatividad, 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)
En términos más generales, cuándo (#)
es la función de datos de quine y f1,f2
son funciones que combinan caracteres con cadenas:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
aplicando la función de datos de quine con (&)=y(f1)
y (%)=y(f2)
, y esto usa los caracteres prescritos f1
y f2
para combinar los datos de quine con x
, y luego pasa la cadena resultante a v
.
El cuerpo de la expresión lambda principal pone todo esto junto:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:x
para un carácter k
antecede &'k'
a la cadena x
, mientras que '%':q:'\\':k:q:x
antepone %'\k'
, que son sus formas originales de datos de quine
- Por
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
lo tanto, son los parámetros correctos para reconstruir la representación de datos de quine, antepuestos al final z
(la cadena vacía) y luego pasados a la siguiente función.
y(:)#y(:)
son los parámetros correctos para anteponer el código central de la quine a una cadena, sin otra modificación.
- Finalmente,
\x->x
no puede hacer nada con la quine construida, que se devuelve.