7 , 410 caracteres, 154 bytes en la codificación de 7, 0 letras = puntaje 154
55104010504200144434451510201304004220120504005434473340353241135014335450302052254241052253052244241052335452241114014241310052340435303052335442302052335500302052335430302052313340435303135014243241310335514052312241341351052302245341351525755102440304030434030421030442030424030455733413512410523142410523030523112411350143355142410523414252410523102410523002410523413342411145257551220304010420030455741403
Pruébalo en línea!
En un desafío que no le gusta usar letras, ¿qué mejor idioma para usar que uno que consta solo de dígitos?
Este es un programa completo que sale por fallas, por lo que hay salidas extrañas a stderr, pero stdout es correcto.
Explicación
Un programa 7, en su primera iteración, simplemente empuja una serie de elementos a la pila (porque de los 12 comandos que existen en 7, solo 8 de ellos pueden representarse en un programa fuente, y esos 8 están especializados para escribir código para empujar estructuras de datos particulares a la pila). Este programa no utiliza el 6
comando (que es la forma más sencilla de crear estructuras anidadas, pero por lo demás no tiende a aparecer literalmente en un programa fuente), por lo que solo los 7
comandos determinan la estructura; 7
empuja un nuevo elemento vacío a la parte superior de la pila (mientras que los comandos 0
... 5
simplemente se agregan a la parte superior de la pila). Por lo tanto, podemos agregar espacios en blanco al programa para mostrar su estructura:
551040105042001444344515102013040042201205040054344 7
33403532411350143354503020522542410522530522442410523354522411140142413100523
40435303052335442302052335500302052335430302052313340435303135014243241310335
514052312241341351052302245341351525 7
55102440304030434030421030442030424030455 7
33413512410523142410523030523112411350143355142410523414252410523102410523002
41052341334241114525 7
551220304010420030455 7
41403
Los elementos cerca del final del programa se empujan al final, por lo que se encuentran en la parte superior de la pila al comienzo de la segunda iteración. En esta iteración, y en todas las futuras, el intérprete 7 realiza automáticamente una copia de la parte superior de la pila y la interpreta como un programa. El literal 41403
empuja el (código en vivo no literal) 47463
(7 tiene 12 comandos pero solo 8 de ellos tienen nombres; como tal, uso negrita para mostrar el código y no negrita para mostrar el literal que genera ese código, lo que significa eso, por ejemplo, 4
es el comando que se agrega 4
al elemento de la pila superior). Entonces, el programa que se ejecuta en la segunda iteración es 47463
. Esto es lo que hace:
47463
4 Intercambie los dos elementos superiores de la pila, agregue un elemento vacío entre
7 Agregue un elemento vacío de la pila a la parte superior de la pila
4 Intercambie los dos elementos superiores de la pila, agregue un elemento vacío entre
6 Encuentre qué comandos generarían el elemento superior de la pila;
agregue eso al elemento a continuación (y haga estallar la parte superior anterior de la pila)
3 Salida del elemento de la pila superior, pop el elemento a continuación
Esto es más fácil de entender si miramos lo que le sucede a la pila:
- ... d c ab un
47463
(código se ejecute: 47463
)
- ... d c b vaciar un (código se ejecute: )
47463
7463
- ... d c b vaciar un vacío (código se ejecute: )
47463
463
- ... d c b vacío vacío vacío un (código se ejecute: )
47463
63
- ... d c b vacío vacío " un " (código se ejecute: )
47463
3
- … D c b vacío (código para ejecutar: vacío )
47463
En otras palabras, tomamos la parte superior de la pila una , el trabajo a cabo lo que el código es más probable que lo han producido, y la salida de ese código. El 7 intérprete saca automáticamente los elementos vacíos desde la parte superior de la pila al final de una iteración, por lo que terminamos con la parte 47463
posterior en la parte superior de la pila, al igual que en el programa original. Debería ser fácil ver lo que sucede después: terminamos revolviendo cada elemento de la pila uno tras otro, mostrándolos todos, hasta que la pila se desborda y el programa se bloquea. Básicamente, hemos creado un bucle de salida simple que analiza el código fuente del programa para determinar qué generar (no estamos generando las estructuras de datos que fueron empujadas a la pila por nuestro 0
...5
comandos, en su lugar, estamos recreando qué comandos se usaron al observar qué estructuras se crearon y generarlas). Por lo tanto, el primer elemento de salida de datos es 551220304010420030455
(el código fuente que genera el segundo elemento de la pila superior), el segundo es 3341351…114525
(el código fuente que genera el tercer elemento de la pila superior), y así sucesivamente.
Obviamente, sin embargo, estas piezas de código fuente no se generan sin codificar. 7 contiene varios idiomas diferentes de dominio específico para codificar la salida; una vez que se elige un idioma específico del dominio, permanece en uso hasta que se borra explícitamente, pero si ninguno de los idiomas se ha elegido todavía, el primer dígito del código que se emite determina cuál de los idiomas usar. En este programa, solo se usan dos idiomas: 551
y 3
.
551
es bastante simple: es básicamente el antiguo código Baudot / teletipo utilizado para transmitir letras sobre teletipos, como un conjunto de caracteres de 5 bits, pero modificado para que todas las letras sean minúsculas. Entonces, el primer fragmento de código que se generará se descodifica de esta manera:
551 22 03 04 01 04 20 03 04 55
c a SP e SP n a SP reset output format
Como se puede ver, estamos ajustando cada carácter en dos dígitos octales, que es una relación de compresión bastante decente. Los pares de dígitos en el rango 0-5 nos dan 36 posibilidades, en oposición a las 32 posibilidades que Baudot necesita, por lo que los cuatro restantes se usan para comandos especiales; en este caso, 55
al final borra el formato de salida recordado, lo que nos permite usar un formato diferente para la siguiente pieza de salida que produzcamos.
3
es conceptualmente aún más simple, pero con un toque diferente. La idea básica es tomar grupos de tres dígitos (nuevamente, en el rango de 0-5, ya que esos son los dígitos para los que podemos garantizar que podemos recrear el código fuente original a partir de su salida), interpretarlos como tres dígitos número en la base 6, y simplemente generarlo como un byte en binario (lo que nos permite generar los caracteres multibyte en la salida deseada simplemente generando múltiples bytes). Sin embargo, el giro proviene del hecho de que solo hay 216 números de tres dígitos (con posibles ceros iniciales) en la base 6, pero 256 bytes posibles. 7 lo resuelve uniendo números desde 332₆ = 128₁₀ hacia arriba a dos bytes diferentes; 332
puede emitir el byte 128 o 192, 333
el byte 129 o el 193, y así sucesivamente, hasta el 515
cual sale el byte 191 o 255.
¿Cómo sabe el programa cuál de las dos posibilidades puede generar? Es posible usar tripletas de dígitos 520
hacia arriba para controlar esto explícitamente, pero en este programa no tenemos que: ¡el valor predeterminado de 7 es elegir todos los bytes ambiguos de tal manera que la salida sea válida UTF-8! Resulta que siempre hay a lo sumo una forma de hacer esto, por lo que siempre que queramos UTF-8 (y lo hagamos en este caso), podemos dejarlo ambiguo y el programa funciona de todos modos.
El final de cada una de las 3…
secciones es 525
, que restablece el formato de salida, lo que nos permite volver a 551
la siguiente sección.
a
s, o no, dependiendo de cuántos tomaría letras, porque 20 caracteres es una penalización realmente grande (aunque cuando todo lo demás se puntúa por bytes, ¡no está muy bien definido ...)!