Ilegible , 3183 3001 bytes
Fue un desafío divertido trabajar dentro y fuera de las celebraciones navideñas. ¡Gracias por tu publicación! Jugar al golf fue interesante porque la especificación está llena de excepciones y casos especiales, que requieren muchas condiciones. Además, aunque esta vez no necesitaba convertir ay desde decimal, sí necesitaba una especie de función "máxima" para determinar el mayor número de dígitos en cada número y el mayor valor de los dígitos en cada lugar.
La primera versión de esto era 4844 bytes, solo para darte una idea de cuánto jugué al golf.
El programa espera la entrada como una lista de enteros separados por comas . Sin espacios ni líneas nuevas. Usarlos producirá un comportamiento indefinido.
'"" "" ""' "" '""' "" '""' "" '"" "'" "" "" "'" ""' "" '""' "" '""' "" '""' "" '""' "" '""' "" "" "" '""' "" '""' "" '""' "" '"" "'" "' "" '""' "" '""' "" '""' "" '""' "" '""' "" '""' "" '""' "" '""' "" '"" '""' "" '""' "" '""' "" '""' "" '""' "" '""' "" '""' "" "" "" '" "" "" "" "'" ""' "" '""' "" '""' "" '"" "" ""' "" '"" "" ""' "" "" " "" '""' "" '""' "" '"" "" "" ""' "" "" "" "" "" "" "" "" "" '"" """" "'" ""' "" "" "" '"" "" "" "'" "" '""' "" "" "" "" "'" "" "" "" " '"" "'" "" "" '""' "" "" "" '""' "" '""' "" "" "" "" "" "" "'" "" "' "" "" "" '""' "" '"" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" '"" "" ""' "" "" "" '"" "" "" "" "" "" "" "" "" "" "'" " '"" "" "'" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" ""' "" '""' "" '"" "'" "" "" "" "" "" "" "" "" "" "'" "'""" '"" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '"" "'" "" "" "" "'" "" "" "" "" "" "'" "" "" "" "" "" '"" "" "" " '"" "" "" "'" "" '"" "" "" "" "" "" "" "" "" "" "" "" "'" "" '"""" "'" "" "" "'" "" '""' "" "" "" "" "" '"" ""' "" "" "" "" "" "'" " '"" "'" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "'" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" """" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" ""' "" "" "" " '"" "" "" ""' "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "'" "'" "' "" '""' "" '""' "" "'" "" ""' "" "" "" "" "" "" "" "" "" "'" "'""" "" "" '""' "" "" "" "" "" "" '"" "" "'" "" "" "" "" "" "" "" "'" "'" "'" "'" ""' "" "" "" "" '""' "" '"" "" "" "" "" "" "'" "" "" "' "" '"" "'" "'" "" "" ""' "" "" "" "" "'" "" ""' "" "" "" '"" "" ""'" "'" "" '"" "" "" ""' "" "" "" "" "'" "" "" "" "" "" "'" "" "" "" "'" "" "" ""' "" "" "" '""' "" '""' "" '""' "" '""' "" "'" "" "" "" " '"" "" "" "'" "'" "'" "'" "'" "'" "'" "'" "" "" "" "" "" "'" "" """ "" '"" "" "" "" "" "" "" "" "" "" ""' "" "" "" "" "" "" '"" "" "" "'" "'" "'" "'" "" '"" "" ""' "" '""' "" "" "" "" "" "" "" "" "" "' "" '"" "" "" "'" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" """" '"" "" "" "'" "'" ""' "" "" '"" "" "" "" "" "" "" "" "" "'" "" "" "" "" '"" "" "" "" "'" "'" "" "" "" "" "" "" "" ""' "" "" "" "" "" "" "'" "" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" '"" """" "'" "" "" ""' "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "'" "" "" "" "" "" "" "" "'" "" "" "" "" "'" "" "" "" " '"" "'" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'"" "" "" "'" "" "" "" "" "" "" "" "" "'" "'" "'" "'" "" '""' "" '" "" "" "" '""' "" '""' "" '""' "" "" "" "" "" "" "" "" "" '"" "" "" " "" "" '""' "" '""' "" '"" "" "" "" ""' "" "" "" "" "" "" "" "" ""'""' "" "" "'" "" "" ""' "" "" "" '""' "" "" "" "" "" "" "" '"" "" "" "'" "'" "'" ""' "" "" "" "" "" "" "'" "'" "" "" "" "" "" '"" "" "" " '"" "" "" "'" "'" ""' "" "" "" "" "" "" '"" "" "" "" "" ""' "" '""'" "'" "" "" "" '""' "" '"" "'" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" '"" "'" "" "" "" "" "" "" '"" "" "" "" "" "" ""' "" "" "" "'" "" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'""' "" '"" "'" "'" "" "" ""' "" '""' "" "" "" "" "" "" "" "" "" "" "'" "" "" "'" "" "" "" '"" "" "" "" "" "" "" "" "" "" "'" "" "" "" '" "'" ""' "" "" "" '"" "" "" "" "'" "" "" '"" "" "" "" "" "" "" "" ""'" "'" "" '"" "" "" "" "" "" "" ""' "" "" "" "" "" "" "" "" "" "" " "" "" '""' "" '"" "'" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "'" "'" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" '"" """ "" "'" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" '"" "'" "" '"" "" "" "" "" ""' "" "" "" "" "" "" '"" "" "'" "'" "" '""' "" "" "" "'" "'" "" '"" "" "" "" "" "" "" "'" "" "" '"" "'""" "" "" "" '"" "" "" "'" "" "" '"" "" "" "" "" "" "" "" "'" "" '"" "'" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "'" "" "" " "'" "" "" ""' "" "'" "" "" "" "'" "" "" "" "" "" "" "" "" "" '"'"" '""' "" '""' "" '""' "" '""' "" "" "" "" "" "" "" "" "" "" "" "' "" "'" "" "" "" "'" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "'" "'" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" '"" "" ""'"" "" "" "'" ""' "" "" "" "" "" "" "" "'" "" "" "" "" "'" ""
Explicación
Le explicaré cómo funciona el programa mostrándole cómo procesa la entrada específica 202,100,1.
Al principio, construimos algunos valores que necesitaremos más tarde, principalmente los códigos ASCII de los caracteres que mostraremos.

Como puedes ver, '8'ya '.'están disponibles. '|', sin embargo, es realmente 124, no 14. Usamos un ciclo while para agregar dos veces el valor temporal en la ranura # 1 para obtener 124 (que es 14 + 55 × 2, porque el ciclo while se ejecuta para 56−1 = 55 iteraciones). Esto ahorra algunos bytes porque los literales enteros grandes como 124 son realmente largos. En el siguiente diagrama, muestro la ubicación de cada variable que usa el programa.

A continuación, queremos ingresar todos los caracteres y almacenarlos en la cinta comenzando en la celda # 12 ( p es el puntero en ejecución para esto). Al mismo tiempo, queremos saber cuánto mide el número más largo (cuántos dígitos). Para lograr esto, mantenemos un total acumulado en unario que va hacia la izquierda comenzando en la celda # -1 (usamos q como el puntero en ejecución). Después del primer número de entrada ( 202), la cinta ahora se ve así:

Habrás notado que los números están apagados en 4. Bueno, cuando los ingresamos por primera vez, son sus valores ASCII, por lo que están "apagados" en 48 y la coma es 44. Para cada carácter, copiamos el 46 de '.'en r y luego lo restamos con un ciclo while (que resta 45) y luego sumamos 1. Hacemos eso para que la coma (nuestro separador) sea 0, de modo que podamos usar un condicional para reconocerlo.
Además, habrás notado que dejamos la celda # 11 en 0. Necesitamos eso para reconocer el límite del primer número.
El siguiente personaje será una coma, por lo que almacenamos un 0 en el n. ° 15, pero, por supuesto, esta vez no avanzamos q . En cambio, establecemos q nuevamente en 0 y comenzamos a "sobrescribir" los 1 que ya hemos colocado.
Después de que se procesen todos los caracteres restantes, obtenemos esto:

Como puede ver, los 1 escritos por q ahora indican (en unario) la longitud del número más largo.
Ahora usamos un bucle while para mover q a la izquierda y luego colocamos otro puntero allí al que llamaré r2 . El propósito de r2 quedará claro más adelante.

En este punto, permítanme aclarar la terminología que usaré a lo largo de esto.
- Por número , me refiero a uno de los números de entrada que están separados por comas. En nuestro ejemplo, son 202, 100 y 1.
- Por dígito , me refiero a un solo dígito en uno específico de los números. El primer número tiene 3 dígitos.
- Por lugar , me refiero al lugar de las unidades, el lugar de las decenas, el lugar de las centenas, etc. Entonces, si digo "los dígitos en el lugar actual", y el lugar actual es el lugar de las unidades, esos dígitos son 2, 0 y 1 en ese orden.
Ahora volvamos a nuestra programación regular. El resto del programa es un gran bucle que avanza q hacia adelante hasta llegar a la celda # 0. Cada una de las celdas en el camino representa un lugar, con las que están ubicadas en el extremo derecho, y q comenzará en el más significativo. En nuestro ejemplo, ese es el lugar de los cientos.
Procedemos incrementando los puntos q de la celda en (es decir, * q ).

Ahora estamos en la "etapa 2" para el lugar de los cientos. En esta etapa, descubriremos cuál es el dígito más grande entre todos los dígitos en el lugar de las centenas. Utilizamos el mismo truco de conteo unario para esto, excepto que esta vez el puntero se llama r y el puntero r2 marca su posición inicial a la que debemos restablecerlo cada vez que pasamos al siguiente número.
Comencemos con el primer número. Comenzamos configurando p en 11 (la posición inicial codificada de todos los números). Luego usamos un ciclo while para encontrar el final del número y establecemos p2 allí para marcar la posición. Al mismo tiempo, también establecemos q2 en 0:

No se distraiga por el hecho de que q2 apunta hacia los vars. No tenemos un relleno de una celda en blanco allí porque podemos detectar la celda # 0 simplemente porque es el número cero.
A continuación, revisamos el número actual disminuyendo p y q2 juntos hasta que * p sea cero. En cada lugar, el valor de * q2 nos dice lo que debemos hacer. 1 significa "no hacer nada", así que seguimos adelante. Finalmente encontramos el 2 en la celda # −3. Cada vez que * q2 no es igual a 1, q2 siempre es igual a q .

Como ya dije, la etapa 2 es "determinar el dígito más grande en este lugar". Por lo tanto, configuramos r en r2 , usamos un bucle while para disminuir * p y movemos r hacia la izquierda y llenamos la cinta con 1s, y luego usamos otro bucle while para mover r de nuevo a la derecha e incrementar * p nuevamente para restaurar el valor. Recuerde que cada ciclo while se ejecuta por una iteración menos que el valor en el que lo usamos; debido a esto, el número de 1s escritos será 3 más (en lugar de 4 más) que el valor del dígito, y el valor final almacenado de nuevo en * p será 2 más. Por lo tanto, esto ha disminuido efectivamente * p en 2.
Después de eso, establecemos p en el valor de p2 y luego hacemos todo eso nuevamente. Por segunda vez, establezca q2 en 0, encuentre el final del número moviendo p hacia la derecha y luego pase por los dígitos de este número decrementando p y q2 juntos. Una vez más, encontraremos el 2 en la celda # −3 y escribiremos los muchos 1 restantes de * r .
En el caso del tercer número, terminamos sin hacer nada porque no tiene un lugar de cientos (por lo que q2 nunca llega a q ), pero está bien porque eso no afecta el cálculo del valor máximo de dígitos.

También configuramos la celda * (r - 4) , que he marcado con una flecha sin etiqueta aquí, a 1 (aunque ya está en 1). No voy a decirte por qué todavía, pero ¿tal vez ya lo has adivinado?
El siguiente incremento de * q nos lleva a la etapa 3, que es "restar el dígito máximo de todos los dígitos en el lugar actual". Como antes, reiniciamos p a 11 y q2 a 0 y luego revisamos todos los números tal como lo hicimos en la etapa anterior; excepto esta vez, * q = 3 en lugar de 2. Cada vez que q2 se encuentra con q y p está en un lugar de cientos, usamos un bucle while para disminuir * p tantas veces como haya 1s en el bloque a la izquierda de * r2 (5 en nuestro ejemplo) usando rcomo un puntero corriendo. De hecho, lo decrementamos una vez más para que el dígito más grande termine en −2, por una razón que se aclarará más adelante:

Después de haber procesado todos los números, ahora estamos al final de la etapa 3. Aquí realizamos dos cosas singulares.
- Primero, también restamos el tamaño del bloque r (más 1) de * q , pero usando el puntero r2 , que lo deja a la izquierda. * q se vuelve negativo de esta manera. En nuestro caso, el bloque r tiene cinco 1s, por lo que * q se convierte en −3.
- En segundo lugar, hemos creado una variable a cabo a un valor distinto de cero para indicar que ahora estamos entrando en la etapa de salida. (Técnicamente, el hecho de que * q sea negativo ya indica la etapa de salida, pero esto es demasiado difícil de verificar, de ahí la variable adicional).
Ahora comprende que seguimos revisando los números, encontramos el lugar actual (indicado por el valor distinto de 1 de * q ) dentro de cada número y hacemos algo según el valor de * q . Vemos que * q se incrementa primero a 2 (= calcular el valor de dígito máximo), luego a 3 (restar el valor de dígito máximo de cada dígito en este lugar) y luego lo restamos para que sea negativo. A partir de ahí, continuará subiendo hasta llegar a 1, restaurando así el valor que significa "no hacer nada". En ese punto, pasamos al siguiente lugar.
Ahora, cuando * q es negativo, estamos generando. * q tiene exactamente el valor correcto para que generemos el número correcto de filas de caracteres antes de que llegue a 1; Si el dígito más grande es 2, necesitamos generar 3 filas. Veamos qué sucede en cada valor de * q :
- * q = −2:
- Para el primer número, * p es −2, lo que indica que necesitamos generar un
'.'(punto) o un ':'(dos puntos). Decidimos qué al mirar q : si es −1, estamos en el lugar de las unidades, por lo que genera a ':'(que calculamos como '8'+2), de lo contrario a '.'.
- Para el segundo número, * p es −3. Cualquier cosa que no sea −2 significa que sacamos una
'|'(tubería) y luego incrementamos el valor. De esta forma alcanzará −2 en el lugar correcto y luego sacaremos '.'s / ':'s para el resto de ese dígito.
- En cada caso, también establecemos una variable pd a 0 antes de procesar el número, y establecemos pd (= "impreso") en un valor distinto de cero para indicar que hemos impreso un carácter.
- Para el tercer número, no se procesa porque el tercer número no tiene un lugar de cientos. En este caso, pd seguirá siendo 0 después de procesar el número, lo que indica que todavía necesitamos generar un
'|'(pero solo si out no es cero, porque de lo contrario todavía estamos en la etapa 2 o 3).
- Después de procesar todos los números, si out no es cero, genera una nueva línea. Tenga en cuenta que necesitamos la variable out para no generar la nueva línea en la etapa 2 o 3.
- * q = −1: Igual que antes, excepto que * p es −2 para los dos primeros números, por lo que ambos generan a
'.'(y el tercero genera a'|'como antes).
- * q = 0: cuando * q es 0, esto significa "no hacer nada si estamos en el lugar de las unidades; de lo contrario, generará una fila de
'|'s independientemente de * p ". De esta manera obtenemos el relleno entre los dígitos.
Ahora incrementamos q para pasar al siguiente lugar, el lugar de las decenas, e incrementamos * q allí. Al comienzo de la Etapa 2, la cinta se ve así:

Luego realizamos la Etapa 2 igual que antes. Recuerde que esto resta efectivamente 2 de cada dígito en este lugar y también deja un número unario a la izquierda de * r2 que indica el dígito máximo. Dejamos solo el número unario anterior y seguimos extendiendo la cinta hacia la izquierda; solo costaría un código adicional innecesario para "limpiar". Cuando terminamos e incrementamos * q , al comienzo de la Etapa 3 la cinta ahora es:

En realidad, esto es una mentira. ¿Recuerdas antes dónde dije que establecimos * (r - 4) en 1 y no te dije por qué? Ahora te diré por qué. Es para casos como este, donde el dígito más grande es de hecho 0, lo que significa que todos los dígitos en este lugar son 0. La configuración * (r - 4) , indicada por la flecha sin etiqueta arriba, a 1 extiende el número unario en 1, pero solo en este caso especial. De esta manera, simulamos que el dígito más grande era 1, lo que significa que mostraremos una fila adicional.
Después de la Etapa 3 (restar el dígito máximo de todos los dígitos en el lugar actual), incluido el paso adicional que hace * q negativo, la cinta se ve así. La última vez que el dígito más grande fue representado por −2 en el bloque * p , pero esta vez son todos −3 porque en realidad todos son ceros, pero estamos fingiendo que el dígito máximo era un 1.

Ahora veamos qué sucede cuando * q avanza hacia 1:
- Cuando * q = −1, los valores * p son todos −3, lo que significa que sacamos
'|'sy los incrementamos.
- Cuando * q = 0, salimos
'|'porque eso es lo que siempre hacemos cuando * q = 0, independientemente de * p .
Por lo tanto, obtenemos dos filas de tuberías.
Finalmente, nos movemos * q a su lugar. Este se pone interesante porque necesitamos generar ':'s si el dígito real es cualquier cosa menos 1, y '8'si es 1. Veamos cómo procede el programa. Primero, incrementamos * q para iniciar la Etapa 2:

Después de la Etapa 2 ("calcular el valor máximo de dígitos"), nos queda esto:

Después de la Etapa 3 ("restar el valor máximo de dígitos de todos los dígitos en el lugar actual") la cinta se ve así:

Ahora veamos cada iteración de * q a su vez:
- * q = −2:
- Primer número: ya está en −2, así que emite a
':'(en lugar de a '.'porque q = −1).
- Segundo número: en −4, de modo que emite a
'|'e incrementa
- Tercer número: en −3, entonces salida a
'|'. Sin embargo, esta vez, en lugar de aumentar, se desencadena un caso especial. Solo si estamos generando el último lugar ( q = −1), y estamos en la penúltima fila para eso ( * q = −2), y el dígito es en realidad un 1 ( * p = −3) , luego , en lugar de incrementarlo a −2, lo configuramos a −1. En otras palabras, usamos -1 como un valor especial para indicar que en la próxima iteración, tendremos que generar en '8'lugar de ':'.
- * q = −1:
- En primer número: ya a -2, por lo que la salida una
':'.
- Segundo número: en −3, entonces salida a
'|'. La condición especial no se activa porque * q ya no es −2. Por lo tanto, incremente.
- Tercer número: en −1, entonces salida
'8'.
- * q = 0: Normalmente, mostraríamos la fila de relleno de
'|'s aquí, pero en el caso especial en el que estamos en el lugar de las unidades ( q = −1), nos saltamos eso.
Después de esto, q se incrementa a 0 y finaliza el ciclo grande while.
Ahora ya sabes cómo funciona una entrada como 202,100,1. Sin embargo, hay un caso especial más que todavía no hemos cubierto. Puede recordar que mientras procesábamos el último lugar, cuando * p era −3 lo configuramos en −1 para el 1(en lugar de incrementarlo a −2) para que la siguiente iteración produzca un '8'en su lugar. Esto solo funciona porque tenemos una iteración en la que * p es −3 y tomamos una decisión sobre si aumentarlo o establecerlo en −1. Nosotros no tenemos una iteración como si todos los dígitos en el lugar de las unidades son 0 ó 1. En este caso, todos los * p valores para los 1s se comienza a cabo a -2; no hay oportunidad de decidir establecerlo en −1en lugar de incrementarlo desde −3 . Debido a esto, hay otra condición de carcasa especial dentro de la Etapa 3 ("restar el dígito máximo de cada dígito en el lugar actual"). Afirmé que después de restar el valor de dígito máximo de cada dígito (en cuyo punto el dígito máximo está en −1), simplemente lo decrementamos una vez más, pero en realidad hay una condición sobre eso que es la siguiente:
Si el dígito que estamos viendo es igual al dígito máximo en este lugar ( * p = −1), y este lugar es el lugar de las unidades ( q = −1), y el dígito máximo es 1 ( * (r + 5) = 0, es decir, el bloque unario a la izquierda tiene solo 5 celdas de largo), solo entonces dejamos * p en −1 para indicar que la única iteración de la salida debe generar un '8'. En todos los demás casos, lo decretamos una vez más.
Hecho. ¡Feliz año nuevo!
Edición 1 (3183 → 3001): ¡ Feliz año nuevo jugando al golf! ¡Logré deshacerme de las variables p2 y r2 por completo! p ahora corre de un lado a otro para seguir encontrando el principio y el final de los números, pero parece ser más corto en código. Traté de deshacerme de q2 también, pero no pude acortar el código de esa manera.
También encontré algunos lugares más donde podría aplicar los típicos trucos de golf ilegibles, como reutilizar el último valor de un ciclo while. Para darle un ejemplo, en lugar de
while *(++p) { 1 } // just increment p until *p is 0; the 1 is a noop
if (pd) { x } else { y } // where pd is a variable
Puedo guardar el '""""(hacer el primero, luego el segundo) y el '"""(constante 1) escribiéndolo de una manera similar a
if (while *(++p) { pd }) { x } else { y }
Por supuesto, esto solo funciona si sé que el ciclo while se ejecutará durante al menos una iteración, pero si lo hace, su valor de retorno es pd, por lo que puedo usarlo como condición para el if.