Haskell , 306 + 624 = 930 bytes
Programa 1: Uma função anônima pegando um argumento fictício e retornando uma string.
(\b c()->foldr(\a->map pred)b(show()>>c)`mappend`show(map(map fromEnum)$tail(show c):pure b))"İĴİóđđđÝöÝâÝæÝääē××êääē××İēÀħđĮâħēĕóİóòòĮááħááđéêâéêēááĮÀħ""(\b c()->foldr(\a->map pred)b(show()>>c)`mappend`show(map(map fromEnum)$tail(show c):pure b))"
Experimente online!
Programa 2: q[[40,...]]
no final, é uma função anônima que pega um argumento fictício e retorna uma string.
z~z=[[['@','0'..]!!4..]!!z]
q[x,q]_=z=<<x++q++[34,34]++x
q[[40,92,98,32,99,40,41,45,62,102,111,108,100,114,40,92,97,45,62,109,97,112,32,112,114,101,100,41,98,40,115,104,111,119,40,41,62,62,99,41,96,109,97,112,112,101,110,100,96,115,104,111,119,40,109,97,112,40,109,97,112,32,102,114,111,109,69,110,117,109,41,36,116,97,105,108,40,115,104,111,119,32,99,41,58,112,117,114,101,32,98,41,41,34],[304,308,304,243,273,273,273,221,246,221,226,221,230,221,228,228,275,215,215,234,228,228,275,215,215,304,275,192,295,273,302,226,295,275,277,243,304,243,242,242,302,225,225,295,225,225,273,233,234,226,233,234,275,225,225,302,192,295]]
Experimente online!
Conjunto de caracteres 1 (inclui espaço):
"$()-:>E\`abcdefhilmnoprstuw×ÝáâäæéêñòóöđēĕħĮİĴ
Conjunto de caracteres 2 (inclui nova linha):
!'+,.0123456789<=@[]_qxz~
Como apenas o conjunto 1 contém caracteres não ASCII, seus bytes UTF-8 também são disjuntos.
Como funciona
O Programa 1 geralmente é escrito com expressões lambda, espaços e parênteses, uso gratuito de funções alfanuméricas incorporadas e com os dados quine como literais de string no final.
- O código principal do próprio programa 1 é transformado em dados literais de cadeia de caracteres simplesmente envolvendo-o entre aspas.
- Para suportar isso, toda barra invertida é seguida por
a
ou b
, que formam seqüências de escape válidas que percorrem o caminho show
.
- Outro pequeno benefício é que
a
, b
e c
são as únicas letras minúsculas cujos códigos ASCII são menores que 100, economizando um dígito na codificação numérica usada pelo programa 2.
- A codificação literal de cadeia de caracteres do código principal do programa 2 é mais ofuscada usando Unicode não ASCII: Cada caractere foi adicionado ao seu ponto de código 182 para garantir que não haja sobreposição com os caracteres originais.
- 182 costumava ser 128, até que percebi que poderia abusar do fato de 182 ter o dobro do comprimento da string literal para o código do programa 1 reduzir a decodificação. (Como bônus, o programa 2 pode usar novas linhas.)
O Programa 2 geralmente é escrito com equações de função de nível superior (exceto a final anônima), literais de caracteres e números decimais, sintaxe de lista / intervalo e operadores, e com os dados quine como uma lista de listas de Int
s no final.
- O código principal do programa 1 é codificado como uma lista de seus pontos de código, com uma citação dupla final.
- O código principal do programa 2 é codificado como a lista de pontos de código da cadeia literal usada no programa 1, ainda deslocada para cima em 182.
Passo a passo, programa 1
b
e c
são os valores das literais de cadeia de caracteres para o programa 2 e 1, respectivamente, dados como argumentos finais para a expressão lambda. ()
é um argumento falso apenas para satisfazer a regra do PPCG de que o programa deve definir uma função.
foldr(\a->map pred)b(show()>>c)
decodifica a string b
no código principal do programa 2 aplicando map pred
a ela um número de vezes igual ao comprimento de show()>>c == c++c
, ou 182
.
tail(show c)
converte a string c
no código principal do programa 1, com uma aspas dupla final anexada.
:pure b
combina isso em uma lista com a sequência b
.
map(map fromEnum)$
converte as seqüências de caracteres em listas de pontos de código.
`mappend`show(...)
serializa a lista de listas resultante e, finalmente, anexa-a ao código principal do programa 2.
Passo a passo, programa 2
- O nível superior
z~z=[[['@','0'..]!!4..]!!z]
é uma função que converte pontos de código em caracteres (necessário para escrever, pois nem todos os caracteres toEnum
estão disponíveis).
- Seu argumento de ponto de código também é chamado
z
. O marcador de preguiça ~
não tem efeito nessa posição, mas evita um caractere de espaço.
['@','0'..]
é um intervalo da lista de passos para trás, começando no código ASCII 64 e pulando 16 para baixo a cada passo.
- A aplicação
!!4
a isso fornece um \NUL
personagem.
- O agrupamento em um
[ ..]
intervalo fornece uma lista de todos os caracteres, que são !!z
indexados.
- O personagem é finalmente envolvido em uma lista de singleton. Isso permite mapear a função
z
nas listas usando em =<<
vez de indisponível map
e <$>
.
- O nível superior
q[x,q]_=z=<<x++q++[34,34]++x
é uma função que constrói o programa 1 a partir da lista de dados quine.
x
são os dados para o núcleo do programa 1 (incluindo uma citação dupla final) e os internos q
são os dados ofuscados para o núcleo do programa 2. _
é outro argumento fictício apenas para tornar a função anônima final uma função em vez de apenas uma string.
x++q++[34,34]++x
concatena as peças, incluindo duas aspas duplas com o código ASCII 34.
z=<<
constrói o programa 1 mapeando z
a concatenação para converter de pontos de código em caracteres.
- A final
q[[40,...]]
é uma função anônima combinada q
com os dados do quine.