Haskell , 3 quines, 1119 bytes
Quine 1, 51 bytes
Uma IO
ação anônima que imprime diretamente no stdout.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Experimente online!
Quine 2, 265 bytes
A função f
pega um argumento fictício e retorna uma string.
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]
Experimente online!
Quine 3, 803 bytes
Tudo depois do LANGUAGE
pragma é uma função desagradável, que pega um argumento fictício e retorna uma string.
{-#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'
Experimente online!
Personagens
Quine 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Como funciona
Quine 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 é uma versão modificada do meu recente Golf, uma resposta quine (com melhorias de H.PWiz):
- Como os programas completos não são necessários,
main=
foi removido.
<>
e $
foram substituídos por seus quase sinônimos mappend
e id
.
Isso libera os caracteres vitais =<>
e o operador útil $
para as outras peças.
Quine 2
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,......]
O Quine 2 usa métodos semelhantes para programar 2 da minha recente resposta mutuamente exclusiva do Quines , mas adaptado para se ajustar diretamente e especialmente para evitar o uso de caracteres literais, necessários para o quine 3. Ambos são alcançados com a ajuda da show
função, que por pura sorte ainda não teve nenhum de seus personagens.
Esse quine usa guias em vez de espaços, mas usei os espaços abaixo para facilitar a leitura.
g
são os dados quine, como uma lista de números inteiros no final do código. Cada número representa um caractere do restante do código.
- Os números são alterados
9
, de modo que a guia é 0
. Isso torna a codificação um pouco mais curta, permitindo que as letras minúsculas da função e dos nomes das variáveis caibam em 2 dígitos.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c]
é uma função para converter um número em um caractere (na verdade, uma cadeia de um caractere).
[[show 9!!0,show 1!!0..]!!6..]
é um intervalo de caracteres que começa com um caractere de tabulação indexado em !!c
.
- O próprio caracter separador é produzido por indexar para outra gama
[show 9!!0,show 1!!0..]
, começando com os caracteres de dígitos '9'
e '1'
e salta para baixo em intervalos de 8.
- Os caracteres do dígito são produzidos pela indexação na
show
sequência do dígito correspondente.
f c=[b=<<g]!!0++show g
é a função principal. c
é um argumento fictício.
b=<<g
usa =<<
para converter cada número em g
seu caractere. (O uso de, =<<
e não por exemplo, map
é o motivo pelo qual ele b
precisa agrupar seu caractere retornado em uma lista.)
show g
fornece a representação da g
lista de ++
strings e concatena as strings.
- Como
=<<
tem precedência menor que ++
, é necessário algum bracketing. Para evitar o uso ()
(reservado para o quine 3), [...]!!0
indexe em uma lista com um elemento.
Quine 3
Por design dos outros quines, o quine 3 ainda tem acesso a parênteses, expressões lambda, literais de caracteres e o construtor string / list :
. Isso será suficiente para construir uma função que precede o código do quine a uma string.
Infelizmente, todas as vogais em letras minúsculas (exceto algumas vezes y
) foram usadas, não deixando funções internas alfanuméricas úteis. Também []""
se foram. Isso não deixa uma maneira normal de construir uma string vazia para começar a fingir o código.
No entanto, quase todas as letras maiúsculas ainda estão disponíveis, portanto, LANGUAGE
é possível um pragma para obter uma extensão de idioma. Novamente, por pura sorte, CPP
(ativar o pré-processador C) é a única extensão de idioma nomeada apenas com letras maiúsculas. E macros CPP geralmente têm nomes em maiúsculas.
Portanto, para obter a string vazia essencial, o quine ativa CPP
, usa a __TIME__
macro para obter uma constante de string da forma "??:??:??"
(convenientemente garantido que sempre tenha o mesmo comprimento) e as correspondências de padrões nela.
{-#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&'{'&'-'&......
Após o pragma da linguagem, o quine consiste em uma expressão lambda vinculando seus parâmetros a esses quatro argumentos (deixando um parâmetro fictício final _
para ser aplicado posteriormente):
q
vinculado a '\''
, fornecendo um caractere de aspas simples;
_:_:_:_:_:_:_:_:z
obrigado a __TIME__
, também conhecido como uma string "??:??:??"
, criando assim z
uma string vazia;
y
ligado a (\(?)v k x->v$k?x)
, um combinador lambda usado para ajudar a converter os dados do quine da forma associada à esquerda ("foldl") para a forma associada à direita ("foldr");
- O operador
(#)
vinculado a \(&)(%)v->v&'{'&'-'&...
, os próprios dados quine.
Os dados quine são fornecidos em uma forma de codificação da Igreja, uma expressão lambda com parâmetros (&)(%)v
.
- Aplicando a expressão a valores específicos para instanciar
(&)
, (%)
e v
, essa codificação pode ser usada para construir o código principal do quine ou para reconstruir a própria representação de dados do quine.
- Pela regra de fixidez padrão de Haskell, torne
&
- %
se operadores associativos deixados dentro do lambda. Assim, os parâmetros dos caracteres são combinados com o inicial v
inicial da esquerda.
- Para a maioria dos caracteres
k
, existe um correspondente &'k'
.
- Quando
k
é '
ou \
, que precisa ser escapado dentro dos literais de caracteres, a codificação é alternativa %'\k'
.
Como a codificação de dados é deixada associativa, mas as seqüências são construídas da maneira associativa correta, o combinador y = (\(?)v k x->v$k?x)
é introduzido para preencher a incompatibilidade.
y(...)
destina-se a criar funções adequadas para uso como dados (&)
e (%)
operadores do quine .
v
é uma função de cadeias de caracteres para cadeias de caracteres (os dados pretendidos do quine v
são exemplos).
k
é um caractere, x
uma sequência e ?
um operador que os combina em uma nova sequência. (Para o código principal (?)=(:)
. Para realmente reconstruir a representação de dados quine, é mais complicado.)
- Assim
y(?)v k = \x->v$k?x
é outra função de strings para strings.
Como um exemplo de como isso muda a associatividade, se (&)=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)
De maneira mais geral, quando (#)
é a função de dados quine e f1,f2
são funções que combinam caracteres com seqüências de caracteres:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
aplicar a função de dados quine com (&)=y(f1)
e (%)=y(f2)
, e isso usa o prescrito f1
e f2
para combinar os caracteres dos dados quine com x
e, em seguida, passa a sequência resultante para v
.
O corpo da expressão principal lambda reúne tudo isso:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:x
para um caractere k
precede &'k'
a sequência x
, enquanto '%':q:'\\':k:q:x
precede %'\k'
, que são seus formulários originais de dados quine.
- Assim,
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
são os parâmetros corretos para reconstruir a representação de dados quine, anexados à final z
(a sequência vazia) e depois transmitidos à função a seguir.
y(:)#y(:)
são os parâmetros corretos para acrescentar o código principal do quine a uma string, sem outra modificação.
- Finalmente, o
\x->x
que não faz nada com o quine construído, que é retornado.