Escriba el programa más corto para convertir cualquier pieza de arte ASCII en una escena animada de nieve que comienza a formarse a partir de la nieve que cae ( ejemplo de JavaScript no golfizado actualizado por última vez el 2011-12-19).
Especificación de entrada : su programa debe aceptar combinaciones arbitrarias de espacios, asteriscos y líneas nuevas. La entrada contendrá como máximo 23 líneas y 80 caracteres por línea. No habrá líneas vacías, pero las líneas pueden consistir solo en espacios en blanco. Se incluirá una nueva línea final y se debe ignorar.
Salida : salida de caracteres ASCII (espacios, asteriscos) y códigos de control (retornos de carro, avances de línea, códigos de escape ANSI, etc.) para la consola de texto de su sistema operativo o emulador de terminal hasta que el usuario finalice manualmente el programa. Puede suponer que la ventana del terminal tiene 80x24 caracteres si su sistema operativo permite esa configuración.
reglas :
- La animación debe ser suave y rápida (se prefieren 15 fps).
- La densidad de nieve debe estar entre 5% y 15%.
- No se puede desplazar más de una pantalla de nieve por segundo. (Eso significa que no se pueden agregar más de 24 líneas de nieve nueva en un segundo período de tiempo).
- La nieve no debe mostrar ningún patrón obvio al entrar en la parte superior de la pantalla; Debe parecer aleatorio.
- El programa debe llenar todas las filas de la pantalla con nieve lo más rápido posible cuando se inicia; El llenado inicial de las filas individuales de la pantalla no debe ser obvio para el espectador.
- La esquina inferior izquierda del arte ASCII de entrada debe estar en la esquina inferior izquierda de la pantalla (Figura 1 para mayor aclaración).
- El área dentro o debajo del arte ASCII no debe llenarse permanentemente con asteriscos. Sin embargo, los asteriscos pueden (pero no están obligados a hacerlo) desplazarse por esta área.
- La nieve no debe acumularse en la parte inferior de la pantalla o encima de la nieve existente, excepto como se muestra en la entrada.
- Los espacios inferiores deben llenarse antes que los superiores, ya que llenar espacios en el orden opuesto hace que la animación del árbol de Navidad se vea muy diferente de la salida de mi código original. (añadido 2011-12-20)
¡Felices vacaciones!
Figura 1: áreas etiquetadas de una pantalla de 80x24
---------------------------New snow added on this line--------------------------
|
|
----------------------------------------------------------+ |
**** | |
Snow MUST fall Snow MAY fall ----------------> **** | |
through this through these **** **** | Snow MUST fall |
area. areas of a **** **** | through this |
completed \---------> **** ****| area. |
ASCII art scene. \ *** **** ****| |
area \ \ ******* **** ****| |
\ \ ******** *** ***| (ALL CAPS terms |
(located in \ \--> ********* *** | have standard |
lower left \ ******* ****** MAY | RFC 2119 |
corner of \ ************* ** fall | meanings.) |
screen) \ *********** here | |
*** +---> **** *** | |
*** | **************** *** | |
| Snow MUST fall *** | **************** *** | |
| through this *** +---> *** | |
| area. *** | **************** *** | |
--+---------------------+*** +---> ***+----+------------------+--
| Snow MUST NOT |****************************| Snow MUST NOT |
V accumulate here. |****************************| accumulate here. V
Entradas de ejemplo
Código Golf Banner
****** ******* ******** ******** ****** ******* ** ********
** ** ** ** ** ** ** ** ** ** ** ** **
** ** ** ** ** ** ** ** ** ** **
** ** ** ** ** ****** ** **** ** ** ** ******
** ** ** ** ** ** ** ** ** ** ** **
** ** ** ** ** ** ** ** ** ** ** ** **
****** ******* ******** ******** ****** ******* ******** **
Stack Overflow Logo
****
****
**** ****
**** ****
**** ****
*** **** ****
******* **** ****
******** *** ***
********* ***
******* ******
************* **
***********
*** **** ***
*** **************** ***
*** **************** ***
*** ***
*** **************** ***
*** ***
****************************
****************************
Arboles de navidad
*
*** *
* ***** ***
*** ******* * *****
***** ********* *** *
* *********** *****
* ************* *******
* *** *************** * *
*** ***** ***************** ***
***** ******* ******************* *****
******* * ********************* *******
********* * *********
* *
Respuestas:
Perl, 196/239 caracteres
Esta solución difiere de su ejemplo de JS en que el patrón se llena de arriba hacia abajo en lugar de de abajo hacia arriba, pero supongo que está bien ya que no dijo nada al respecto en las reglas.
Se puede obtener una reducción trivial de 1 carácter reemplazando
\e
con un carácter ESC literal, pero eso hace que el código sea mucho más difícil de leer y editar.Actualización: Me hice las arreglan para llegar a una versión que llena el patrón de arriba abajo, y no permite que la nieve caiga a través de las partes llenas del patrón, como en el ejemplo de implementación JS, al precio de 43 caracteres adicionales:
Reemplazar
($s[$_]&=~$f[$_])
con solo$s[$_]
ahorrará 11 caracteres al permitir que la nieve que cae pase a través de las partes rellenas del patrón (que coincide con la especificación, pero no con la implementación del ejemplo).De acuerdo, dado que todavía parece estar liderando la carrera después de una semana, creo que debería explicar cómo funciona mi solución para fomentar una mayor competencia. (Nota: esta explicación es para la versión de relleno de arriba a abajo de 196 caracteres. Puedo modificarla para incluir la otra versión más adelante).
En primer lugar, el gran truco en el que se basa mi solución es que, debido a la forma en que se organizan los códigos de caracteres ASCII, los 1 bits en el código ASCII para un espacio resultan ser un subconjunto de aquellos en el código para un asterisco.
Por lo tanto, las siguientes expresiones son verdaderas:
" " & "*" eq " "
y" " | "*" eq "*"
. Esto es lo que me permite usar operaciones de cadena bit a bit para combinar las partes estáticas y en movimiento de la escena sin tener que recorrer los caracteres individuales.Entonces, con eso fuera del camino, repasemos el código. Aquí hay una versión sin golf:
La primera línea configura las matrices
@f
(para "fijo") y@p
(para "patrón").@f
formará la parte fija de la pantalla y comenzará con nada más que espacios, mientras@p
que, que no se muestra directamente, contiene el patrón de entrada; A medida que avanza la animación, agregaremos más y más asteriscos@f
hasta que finalmente se vea igual@p
.Específicamente, se
@f = ($" x 80) x 23
establece@f
en 24 cadenas de 80 espacios cada una. ($"
es una variable Perl especial cuyo valor predeterminado resulta ser un espacio). Luego tomamos esta lista, agregamos las líneas de entrada con el operador readline<>
, tomamos las últimas 24 líneas de esta lista combinada y la asignamos a@p
: esto es Una forma compacta de rellenar@p
con líneas en blanco para que el patrón aparezca donde debería. Finalmente,chomp
introducimos las líneas de entrada@p
para eliminar las nuevas líneas finales para que no causen problemas más adelante.Ahora, veamos el bucle principal. Resulta que
{...;redo}
es una forma más corta de escribir un bucle infinito quewhile(1){...}
o inclusofor(;;){...}
, especialmente si omitimos el punto y coma antesredo
porque inmediatamente sigue a unif
bloque.La primera línea del bucle principal introduce la matriz
@s
(para "nieve", por supuesto), a la que antepone una cadena aleatoria de 80 caracteres de 90% de espacios y 10% de asteriscos en cada iteración. (Para guardar algunos caracteres, en realidad nunca saco líneas adicionales del final de la@s
matriz, por lo que cada vez se alarga más y más. Eventualmente eso detendrá el programa a medida que la matriz se alargue demasiado para caber en la memoria, pero eso tomará mucho más tiempo de lo que la mayoría de la gente vería esta animación. Agregar unapop@s;
declaración antes de queselect
lo arreglaría al costo de siete caracteres).El resto del bucle principal está envuelto en un
if
bloque, por lo que solo se ejecuta una vez que la@s
matriz contiene al menos 24 líneas. Esta es una manera simple de cumplir con la especificación, que requiere que toda la pantalla se llene con nieve que cae desde el principio, y también simplifica un poco las operaciones bit a bit.Luego viene un
foreach
bucle, que en la versión de golf es en realidad una sola declaración con unfor 0..23
modificador. Dado que el contenido del bucle probablemente necesita alguna explicación, lo descomprimiré un poco más abajo:En primer lugar,
$_
es la variable de contador de bucle predeterminada en Perl a menos que se especifique otra variable. Aquí se ejecuta de 0 a 23, es decir, sobre las 24 líneas en el marco de la pantalla.$foo[$_]
denota el elemento indexado por$_
en la matriz@foo
.En la primera línea del bucle de golf, imprimimos una nueva línea (obtenida convenientemente de la
$/
variable especial) o, cuando$_
es igual a 0, la cadena"\e[H"
, donde\e
denota un carácter ESC. Este es un código de control de terminal ANSI que mueve el cursor a la esquina superior izquierda de la pantalla. Técnicamente, podríamos omitir eso si asumimos un tamaño de pantalla específico, pero lo mantuve en esta versión, ya que significa que no tengo que cambiar el tamaño de mi terminal para ejecutar la animación.En la
$t = $f[$_]
línea, simplemente guardamos el valor actual de$f[$_]
en una variable "temporal" (por lo tanto$t
) antes de cambiarlo potencialmente en la siguiente línea, donde$s[$_] & $p[$_]
da la intersección (Y bit a bit) de la nieve que cae y el patrón de entrada, y los|=
operadores OR eso en la línea de salida fija$f[$_]
.En la línea debajo de eso,
$t ^ $f[$_]
da el XOR bit a bit de los valores anteriores y actuales de$f[$_]
, es decir, una lista de los bits que cambiamos en la línea anterior, si existe, y al negar cualquiera de las cadenas de entrada con~
la salida. Por lo tanto, lo que obtenemos es una máscara de bits con todos los bits establecidos en 1, excepto los que acabamos de agregar$f[$_]
en la línea anterior. ANDing esa máscara de bits$s[$_]
elimina esos bits; en efecto, esto significa que cuando un copo de nieve que cae llena un agujero en el patrón fijo, se elimina del conjunto de nieve que cae.Finalmente,
print $f[$_] | $s[$_]
(que en la versión de golf se implementa simplemente ORing las dos líneas anteriores juntas) simplemente imprime la unión (OR bit a bit) de los copos de nieve fijos y móviles en la línea actual.Una cosa más que queda por explicar es
select '', '', '', 0.1
debajo del bucle interno. Esta es solo una forma perezosa de dormir 0.1 segundos en Perl; Por alguna razón histórica tonta, elsleep
comando Perl estándar tiene una resolución de un segundo, y la importación de un mejorsleep
desde elTime::HiRes
módulo requiere más caracteres que abusar de 4-argselect
.fuente
say
), a costa de 2 caracteres adicionales. Sin embargo, no creo que pueda cambiar el orden de llenado muy fácilmente; mi implementación está fundamentalmente ligada a esto.HTML y JavaScript, 436 caracteres
Anteponerlo a la entrada:
Vea cómo se ejecuta para cada ejemplo: código de golf , logotipo de Stack Overflow , árboles de Navidad . Los usuarios de Internet Explorer deben ejecutar la versión 9 y configurar el "Modo de documento" en "estándares IE9" (usando las herramientas de desarrollo F12) para que este envío funcione correctamente.
fuente
Python, 299 caracteres
Esto debe cumplir con las reglas, suponiendo que la nueva línea esté incluida en el límite de 80 caracteres.
fuente
a
y desordena la indexación. Acabo de probarlo, y parece que reemplazarlo%e
con la%e.rstrip()
línea 6 soluciona el problema. (Por supuesto, puede haber una solución más corta; no soy bueno en Python golf.)Java, 625 caracteres
Una solución simple en Java.
fuente
"\033[H"
debería hacerlo).