Haskell , 306 + 624 = 930 bytes
Programa 1: una función anónima que toma un argumento ficticio y devuelve una cadena.
(\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))"
Pruébalo en línea!
Programa 2: q[[40,...]]
al final es una función anónima que toma un argumento ficticio y devuelve una cadena.
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]]
Pruébalo en línea!
Conjunto de caracteres 1 (incluye espacio):
"$()-:>E\`abcdefhilmnoprstuw×ÝáâäæéêñòóöđēĕħĮİĴ
Conjunto de caracteres 2 (incluye nueva línea):
!'+,.0123456789<=@[]_qxz~
Como solo el conjunto 1 contiene caracteres no ASCII, sus bytes UTF-8 también son disjuntos.
Cómo funciona
El programa 1 generalmente se escribe con expresiones lambda, espacios y paréntesis, uso libre de funciones alfanuméricas integradas y con los datos de quine como literales de cadena al final.
- El propio código central del Programa 1 se convierte en datos literales de cadena simplemente rodeándolo con comillas.
- Para respaldar esto, cada barra invertida va seguida de
a
o b
, que forman secuencias de escape válidas que se realizan de manera circular show
.
- Otro pequeño beneficio es que
a
, b
y c
son las únicas letras minúsculas cuyos códigos ASCII son inferiores a 100, ahorrando un dígito en la codificación numérica utilizada por el programa 2.
- La codificación literal de cadena del código central del programa 2 está más ofuscada al usar Unicode no ASCII: cada carácter tiene 182 agregados a su punto de código para garantizar que no haya superposición con los caracteres originales.
- 182 solía ser 128, hasta que me di cuenta de que podía abusar del hecho de que 182 es el doble de la longitud del literal de cadena para que el código del programa 1 acorte la decodificación. (Como beneficio adicional, el programa 2 puede usar nuevas líneas).
El programa 2 generalmente se escribe con ecuaciones de función de nivel superior (excepto la anónima final), literales de caracteres y números decimales, sintaxis de lista / rango y operadores, y con los datos de quine como una lista de listas de Int
s al final.
- El código central del Programa 1 está codificado como una lista de sus puntos de código, con una doble comilla final.
- El código central del programa 2 está codificado como la lista de puntos de código del literal de cadena utilizado en el programa 1, aún desplazado hacia arriba por 182.
Tutorial, programa 1
b
y c
son los valores de los literales de cadena para el programa 2 y 1, respectivamente, dados como argumentos finales a la expresión lambda. ()
es un argumento ficticio únicamente para satisfacer la regla de PPCG de que el programa debe definir una función.
foldr(\a->map pred)b(show()>>c)
decodifica la cadena b
al código central del programa 2 aplicándolo map pred
varias veces igual a la longitud de show()>>c == c++c
, o 182
.
tail(show c)
convierte la cadena c
al código central del programa 1, con una doble comilla final añadida.
:pure b
combina esto en una lista con la cadena b
.
map(map fromEnum)$
Convierte las cadenas en listas de puntos de código.
`mappend`show(...)
serializa la lista de listas resultante y finalmente la agrega al código central del programa 2.
Tutorial, programa 2
- El nivel superior
z~z=[[['@','0'..]!!4..]!!z]
es una función que convierte los puntos de código en caracteres (necesarios para escribir, ya que no todos los caracteres toEnum
están disponibles).
- Su argumento de punto de código también se llama
z
. El marcador de pereza ~
no tiene efecto en esta posición, pero evita un carácter de espacio.
['@','0'..]
es un rango de lista de pasos hacia atrás que comienza en el código ASCII 64, y luego salta 16 en cada paso
- Aplicar
!!4
esto da un \NUL
carácter.
- Ajustar eso en un
[ ..]
rango proporciona una lista de todos los caracteres, que !!z
indexa.
- El personaje finalmente se envuelve en una lista singleton. Esto permite mapear la función
z
sobre listas usando en =<<
lugar de las no disponibles map
y <$>
.
- El nivel superior
q[x,q]_=z=<<x++q++[34,34]++x
es una función que construye el programa 1 de la lista de datos de quine.
x
son los datos para el núcleo del programa 1 (incluida una comilla doble final) y el interno q
son los datos ofuscados para el núcleo del programa 2. _
es otro argumento ficticio únicamente para hacer que la función anónima final sea una función en lugar de solo una cadena.
x++q++[34,34]++x
concatena las piezas, incluidas dos comillas dobles con código ASCII 34.
z=<<
construye el programa 1 mapeando z
sobre la concatenación para convertir de puntos de código a caracteres.
- La final
q[[40,...]]
es una función anónima que se combina q
con los datos de quine.