¡Vamos a animarnos!

8

El reto

Los GIF son el formato de imagen más común para la animación, y se usan bastante en las redes sociales actuales. Para el propósito de este desafío, voy a redefinir lo que puede ser un GIF. Este desafío requerirá que tome una matriz 3D que contenga algún tipo de representación de una 'imagen' 2D e itere a través de ellas, mostrando una animación. Esta animación se puede hacer en cualquier lugar, en un GIF, en su consola, en una GUI, etc. la entrega no importa, siempre y cuando sea animada.

La entrada

  • Una matriz 3D donde los datos dentro de alguna manera representan una imagen 2D.
    • La matriz puede contener datos RGB, datos verdaderos / falsos o cualquier otra cosa que considere conveniente.
    • También estoy de acuerdo con que lo reduzca a una matriz 2D de cadenas o algo similar, pero la animación debe ser una animación 2D .
  • El tiempo entre cada cuadro en un formato de su elección (Segundos, Milisegundos, etc.).
    • La gente me pregunta si TIENEN que incluir o no la duración. Mi respuesta es "meh", siempre que pueda mostrar animación. Me preocupa más que se adhiera al parámetro "Array" que este, lo que significa que no hay animaciones aleatorias.

La salida

  • Una secuencia de salida perfectamente iterada que se parece a una animación 2D con el retraso correcto en cada transición en función de la entrada de valor.

Las normas

  • La salida puede ser, pero no se limita a:
    • Imagen GIF
    • Animación GUI (mi ejemplo).
    • Animación en consola.
    • Honestamente, cualquier "animación" que creas conveniente, siempre y cuando siga las siguientes reglas.
  • Al generar su imagen, debe borrar la consola antes de mostrar el siguiente cuadro, no puede simplemente imprimirlos secuencialmente.
    • Emular una consola "limpia" también es aceptable, siempre y cuando parezca una animación perfecta (vea la pista debajo de mi ejemplo para obtener más información sobre lo que quiero decir).
  • Independientemente de la implementación, su animación debe repetirse para siempre o hasta que se detenga.
    • El "bucle" puede ser tan simple como while(true){}una recursión infinita, puede suponer que el usuario quiere ver esta obra maestra hasta que presione "Ctrl + C".
  • Debe poder manejar 'imágenes' en 2D de cualquier tamaño, si su idioma está limitado por los tamaños del búfer, esto es aceptable y puede indicarlo en su explicación.
  • Las lagunas estándar no están permitidas.

Ejemplo de E / S

Entrada (matriz 3D, retraso)

f([
  [[1,0,0],
   [0,0,0],
   [0,0,0]],
  [[0,0,0],
   [0,1,0],
   [0,0,0]],
  [[0,0,0],
   [0,0,0],
   [0,0,1]],
], 1)

Salida (Ejemplo, Bytes 2020 - Java)

import javax.swing.JFrame;
import javax.swing.JTextArea;

/**
 * Simple GIF class to animate a 3D integer array in a swing text area.
 * (Clearing the console in java isn't something you really do, so I chose
 * java on purpose to make it an extremely ungolf-able answer that someone
 * wouldn't bother to steal).
 */
public class Gif implements Runnable {
    /**
     * The output area.
     */
    private final JTextArea area;

    /**
     * The list of images.
     */
    private final int[][][] images;

    /**
     * The delay between image transitions.
     */
    private final long transitionDelay;

    /**
     * Main method, instantiates a GIF object and runs it.
     * @param args Does absolutely nothing.
     */
    public static void main(String[] args) {
        final int[][][] images = {{{1,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,1,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,1}}};
        final long transitionDelay = 1000L;
        new Thread(new Gif(images, transitionDelay)).start();
    }

    /**
     * Constructor for a GIF, takes in a 3D array of images and a transition
     * delay to wait between transitioning the images.
     * @param images The list of images.
     * @param delay The delay between each image.
     */
    public Gif(int[][][] images, long transitionDelay) {
        this.images = images;
        this.transitionDelay = transitionDelay;
        this.area = new JTextArea();
        final JFrame frame = new JFrame("It's a GIF!");
        frame.setSize(10,100);
        frame.add(area);
        frame.setVisible(true);
    }

    /**
     * When run, it will alter the area to imitate an animated GIF.
     */
    @Override
    public void run() {
        while (true) {
            for (int i = 0; i < images.length; i++) {
                final StringBuffer frame = new StringBuffer();
                for (int j = 0; j < images[i].length; j++) {
                    for (int k = 0; k < images[i][j].length; k++) {
                        frame.append("" + images[i][j][k]);
                    }
                    frame.append("\n");
                }
                this.area.setText(frame.toString());
                try{Thread.sleep(transitionDelay);}catch(Exception e){}
                this.area.setText("");
            }
        }
    }
}

Esto da como resultado una GUI de swing emergente, animando la matriz:

Frame One Frame Two Frame Three

SUGERENCIA SUGERENCIA: use un idioma donde sea posible limpiar la consola o especifique por qué lo que está haciendo terminará con un resultado que parece una animación en el idioma que eligió. Creo que algunos idiomas tienen tamaños de búfer predeterminados en sus consolas, puede usar esto para su ventaja, pero espero una explicación o ejemplo. Solo porque produzco mi animación como una cadena, no es necesario; Podría haber usado con la misma facilidad 0 para negro y 1 para blanco y crear un GIF real.

Juzgar

Este es el código de golf, el conteo de bytes más bajo gana (entradas excluidas).
También haré +1 en cualquier persona que use un idioma de manera genial o inesperada.

Urna de pulpo mágico
fuente
¿Cuántas líneas tiene que ser "claro"? ¿Puede ser el mismo número de caracteres por línea?
Riley
Desafío similar con una entrada más estricta: codegolf.stackexchange.com/questions/27101/…
luser droog
@Riley No estoy seguro de que entiendo lo que estás preguntando. Lo claro es esencialmente mantener la salida en la misma línea; es posible que su código no "borre" nada, sino que también lo reemplace en línea. No me importa cómo logras la animación, más que esencialmente funciona usando marcos.
Magic Octopus Urn
@luserdroog No había visto ese, pero también vi uno en "crear una escena de nieve", pero tampoco veo lo suficientemente cerca como para justificar no publicar esto.
Magic Octopus Urn
1
@carusocomputing No se preocupe, más que feliz de hacer la revisión gramatical. Por cierto, en términos de qué idioma se usa para la animación, ¿importa si ya no es uno de uso popular?
Monomeeth

Respuestas:

3

MATL , 16 12 11 bytes

`G@)D1Y.XxT

La entrada es una matriz de celdas de 2D. Por ejemplo:

{[1 0 0; 0 0 0; 0 0 0] [0 0 0; 0 1 0; 0 0 0] [0 0 0; 0 0 0; 0 0 1]}

El tiempo de pausa está 1en el código. Se puede cambiar a cualquier número real, como .5o `.2.

¡Pruébalo en MATL Online! (Si no funciona, actualice la página y presione "Ejecutar" nuevamente).

La entrada también puede ser una matriz de celdas de matrices de caracteres 2D. Por ejemplo:

{['x...';'+...';'....';'....'] ['+x..';'....';'....';'....'] ['.+x.';'....';'....';'....'] ['..+x';'....';'....';'....'] ['...+';'...x';'....';'....'] ['....';'...+';'...x';'....'] ['....';'....';'...+';'...x'] ['....';'....';'....';'..x+'] ['....';'....';'....';'.x+.'] ['....';'....';'....';'x+..'] ['....';'....';'x...';'+...'] ['....';'x...';'+...';'....']}

¡Prueba este también!

Explicación

`       % Do...while
  G     %   Push input: cell array
  @     %   Push iteration index
  )     %   Index to obtain that cell. This uses modular indexing,
        %   so each cell is addressed cyclically
  D     %   Display
  1     %   Push 1: number of seconds to pause
  Y.    %   Pause for that many seconds
  Xx    %   Clear screen
  T     %   True. This is used as loop condition: infinite loop
        % End. Implicitly end do...while loop  
Luis Mendo
fuente
1
¿Puedes guardar algunos bytes usando mi truco? Llenar la matriz con [0.2 0 0.2;0 0.2 0] ... , y así reducir xxa x, y evitar 1Gy 2G? Creo que se adhiere a las reglas. Es necesario añadir unos pocos bytes con el fin de convertir 0.2a 1, si no quiere 0.2saltar alrededor, por supuesto, y de alguna manera para almacenar el valor de pausa. Todavía creo que podría reducir el conteo de bytes :) :)
Stewie Griffin
1
@Weeingitfirst ¡Gracias! Bueno, el desafío especifica dos entradas: la matriz y la pausa, por lo que creo que ambas son necesarias. Esperemos la confirmación de todos modos
Luis Mendo
2
Guau. Seguiste el resumen perfectamente, incluso adhiriéndote a las entradas. Esta es una respuesta muy impresionante. Definitivamente será difícil de superar, y en comparación con las respuestas que no incluyeron la duración de la pausa, esto es básicamente perfecto, bravo.
Urna mágica de pulpo
1
@carusocomputing ¡Genial! Gracias por hacérmelo saber. ¡4 bytes de descuento! La duración aún se puede cambiar, es bastante obvio en el código
Luis Mendo
1
Voy a ser honesto, dudo que esto vaya a ser superado, así que hasta más presentaciones, lo marcaré como la mejor respuesta.
Magic Octopus Urn
2

Octava, 56 54 47 bytes

Se eliminó la posibilidad de ingresar el tiempo de pausa como parte de la matriz de entrada. Estaba muy satisfecho con él, así que eche un vistazo en el historial de edición si desea echar un vistazo. Esta solución es 7 bytes más corta.

n=input('');while(any(n=~n))spy(n);pause(1);end

n=input('');  % Takes input as a matrix of zeros and ones

k=n(1);       % maximum of the input matrix is the desired pause time. Have to store
              % this, because n is soon to be messed with
              % NOTE: k=n(1); is not needed anymore, since the pause time can be hardcoded!

any(n=~n)     % Check if there are any truthy values in `n` (there is), and at the 
              % same time negate it, thus creating a matrix where all elements
              % alternates between 1 and 0.
while(any(n=~n))   % Loop as long as there are any non-zero elements (always some)
spy(n)        % Create a spy-plot where all non-zero elements are shown as a dot
pause(1)      % Pauses for k seconds
end           % ends the loop (will never happen, since it's infinite).

La entrada será algo como esto: [4 0 0 4;0 4 4 0;4 0 0 0]donde será una matriz de dimensiones 3x4, y el tiempo de pausa deseado es de 4 segundos.

Muestra una gráfica como la siguiente, pero alterna entre mostrar los valores verdadero y falso de la entrada. Entonces, todos los puntos azules se volverán blancos en la próxima iteración, y todos los blancos se volverán azules.

En la siguiente gráfica, utilicé la entrada rand(10,10)>0.6*2. Esto significa que tendrá dimensiones de 10x10, y todos los elementos de la matriz aleatoria que sean mayores que 0.6 serán verdaderos. Después de eso, lo multiplico por el tiempo de pausa deseado, 2 segundos. Aquí utilicé una matriz aleatoria, pero también podría haber creado la matriz manualmente.

No tengo Octave instalado en esta computadora, así que hice una pequeña modificación para que esto funcione en MATLAB. Es exactamente el mismo principio, pero n=~nno funciona en MATLAB.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Stewie Griffin
fuente
2
@carusocomputing, ¿debo tomar el tiempo de pausa como entrada o puedo elegirlo yo mismo? Por ejemplo, siempre tiene 1 segundo?
Stewie Griffin
1
@carusocomputing, también: ¿Está bien permitir que el usuario elija el tiempo de pausa, pero no lo tiene como un parámetro separado? En mi opinión no tan humilde, esto califica como: "una forma genial o inesperada" ;-)
Stewie Griffin
1
Sí, estoy completamente de acuerdo, esto califica; siempre y cuando permita que el usuario especifique algún parámetro de entrada y no esté completamente aleatorizado, creo que está bien. El punto central de la pausa era poder ver la animación. No quería ninguno para los bucles donde la gente dice, "bueno, no puedes verlo, pero definitivamente es animado".
Urna mágica de pulpo
1
Además, me gustaron tus dos ideas; el "Generador estático de TV" fue una implementación muy singular, que utilizaba la aleatorización, que ni siquiera consideré. Esto también es impresionante, ya que logró tomar la primera iteración y adherirse más al resumen. Gran trabajo hombre.
Urna mágica del pulpo
2

sed 141134 90

-51 gracias a seshoumara

/^$/!{H;d}
:;/^$/g;s,^\n,,;s,$, ,;s,^,\d27[2J,p
:p;P;s,[^\n]*\n,,;/^ \n/!bp;N;s,[ \n]*,,;b

Entrada: Primero toma cada fotograma separado por una línea con un solo espacio y luego muestra el siguiente fotograma después de recibir cada línea en blanco (parece un flipbook). Mínimo 3 cuadros.

Por defecto en mi sistema (Windows 7) cuando abro cygwin tiene 24 líneas verticalmente. Entre cuadros, siempre hay al menos esa cantidad de líneas en blanco impresas. Esto efectivamente borra la pantalla.

Más de 1/3 de los bytes provienen de limpiar la consola. Estoy seguro de que hay una mejor manera.

Riley
fuente
1
Puede reducir 1 byte al tener el primer pcomando como parte de s///p, más 6 bytes más al eliminar /^\n/!antes P, lo que creo que no es necesario. Por el esfuerzo, +1, aunque también estoy seguro de que hay una mejor manera.
seshoumara
1
Después de un tiempo de navegación en Internet, encontré una manera simple de manipular el cursor del terminal, limpiando así una pantalla: usando las secuencias de escape ANSI. El mecanismo también se utiliza para imprimir texto en colores. Consulte mi respuesta para obtener detalles y un ejemplo de uso. No sé si funcionan en Cygwin, pero puedes intentarlo.
seshoumara
@seshoumara Funciona en cygwin cuando proviene sed, pero por alguna razón no funciona con cato echo.
Riley
Tratar echo -e "\e[2Jtest". Con cat, el carácter de escape ya debe estar en el archivo / entrada, intente echo -e "\e[2Jtest"|cat -ndesplazarse hacia arriba.
seshoumara
@seshoumara Sabía que tenía que ser algo así. ¡Gracias!
Riley
2

GNU sed, 88 84 + 1 (n flag) = 85 bytes

Editar: 3 bytes menos gracias a Riley

H;1h;${:
g;s:\n.*::;H;x;s:[^\n]*\n::;x;y:,:\n:;s:^:ESC[2J:;s:ESC:\d27:gp;esleep 1
b}

El formato de entrada es un cuadro de animación por línea. Para varias líneas de salida en un marco, use una coma como separador. Como ejecuto el programa en una consola Linux, el tamaño máximo de imagen disponible (medido en filas y columnas) depende del tamaño de la ventana del terminal. La pausa entre dos cuadros se realiza mediante el comando sleep shell; para obtener una llamada de animación más rápida esleep 0.4(segundos).

100,000,000            # The timer could be read from the input as well, but that
000,010,000            #would require a lot more bytes and I understand I'm allowed
000,000,001            #to hardcode the value.

¡La mejor parte es que apoyo la animación en color! Para hacer esto, utilicé las llamadas secuencias de escape ANSI para controlar la fuente del texto, el primer plano y el color de fondo, además de la posición del cursor, para poder borrar la pantalla antes de cada fotograma (código ESC[2J). Para agregar información de color, use el siguiente formato en la entrada, que se explica mejor aquí .

ESC[$FORMATm$textESC[0m     # 'ESC' is an actual string, it is then replaced
                            #in sed by the character with the ASCII value 27

Correr:

sed -nf animate.sed input.txt

Ejemplos: para cada prueba, se capturaron 2 ciclos de animación y se guardaron en formato GIF de imagen (disculpas por la baja resolución)

Pausa de 0,4 segundos ¡Feliz cumpleaños!

1 segundo por defecto movimiento "pixel"

Explicación:

H;1h                           # read each line/frame and store them in hold space
${:                            # when the input was read, start a loop
   g                           # copy hold space to pattern space
   s:\n.*::                    # remove all except the first/current frame
   H                           # append frame to hold space
   x;s:[^\n]*\n::;x            # delete first frame from hold space
   y:,:\n:                     # replace all commas with a newline
   s:^:ESC[2J:;s:ESC:\d27:gp   # use an ANSI Escape Sequence to clear the screen
                               #and print frame in color
   esleep 1                    # wait 1 second
b}                             # repeat
seshoumara
fuente
Puede guardar algunos bytes reemplazándolos 1h;1d;H;conH;1h;
Riley
@Riley Gracias, actualicé el código.
seshoumara
Wow, esto fue más profundo que muchos de los otros, me gusta el soporte de color y es la única respuesta que lo hace :). Uso bastante único de las nuevas líneas también. +1 para soporte de color y la singularidad de la respuesta en sí. ¡Honestamente, no lo habría creído si no lo hubiera visto yo mismo!
Magic Octopus Urn
1

Ruby, 89 45 bytes

f=->h,t{h.cycle{|x|puts"^[[2J",x.map(&:join)}}

El ^[es un personaje de escape.

Hexdump:

00000000: 663d 2d3e 682c 747b 682e 6379 636c 657b  f=->h,t{h.cycle{
00000010: 7c78 7c70 7574 7322 1b5b 324a 222c 782e  |x|puts".[2J",x.
00000020: 6d61 7028 263a 6a6f 696e 297d 7d         map(&:join)}}

Ahorrado un montón de bytes gracias a @Jordan

TuxCrafting
fuente
@DLosc Ah, sí, arreglando
TuxCrafting
Puede guardar muchos bytes aquí. ->h,t{h.cycle{|x|puts"^[[2J",x.map(&:join)}}
Jordan
Buena respuesta, también como un FYI se cambió el resumen, ya no tiene que cumplir con la duración como entrada, ya que esto restringe los idiomas posibles. Solo necesita hacer una pausa para que la animación sea aparente.
Magic Octopus Urn
1

Lua ( LÖVE ), 296 287 bytes

c=0;f=1;t=10;l=love
function l.load()loadstring('i='..arg[2])()s=tonumber(arg[3])end
function l.update(d)if c>s then
c=0;f=f==#i and 1 or f+1
end;c=c+d;end
function l.draw()for K,V in pairs(i[f])do
for k,v in pairs(V)do if v>0 then l.graphics.rectangle('fill',k*t,K*t,t,t)end
end
end
end

Ejemplo de uso

love main.love '{{{1,0,0},{0,0,0},{0,0,0}},{{0,1,0},{0,0,0},{0,0,0}},{{0,0,1},{0,0,0},{0,0,0}},{{0,0,0},{0,0,1},{0,0,0}},{{0,0,0},{0,0,0},{0,0,1}},{{0,0,0},{0,0,0},{0,1,0}},{{0,0,0},{0,0,0},{1,0,0}},{{0,0,0},{1,0,0},{0,0,0}},{{1,0,0},{1,0,0},{0,0,0}},{{1,1,0},{1,0,0},{0,0,0}},{{1,1,1},{1,0,0},{0,0,0}},{{1,1,1},{1,0,1},{0,0,0}},{{1,1,1},{1,0,1},{0,0,1}},{{1,1,1},{1,0,1},{0,1,1}},{{1,1,1},{1,0,1},{1,1,1}},{{1,1,1},{1,1,1},{1,1,1}},{{0,0,0},{0,0,0},{0,0,0}}}' 1

Salida : https://youtu.be/0kDhPbbyG9E

Master_ex
fuente
Hmm, no he tenido mucha exposición a lua, no sabía que también tenía soporte gráfico, pero sabía que tenía un gran rendimiento. Una respuesta muy interesante e inesperada. Esta es probablemente la respuesta más cercana a permitir la entrada de color según los números pasados. También la primera respuesta para no usar ASCII, a pesar del alto conteo de bytes, gran trabajo hombre +1 por su singularidad.
Urna de pulpo mágico
1
@carusocomputing ¡Gracias! LÖVE es un marco para hacer juegos en 2D. Deberías
echarle un
Oh hombre, de verdad? ¿Puedes vincularme con alguno de tus otros trabajadores? Me encantaría verlo, amigo.
Magic Octopus Urn
1

SmallBasic, 167 bytes

Como parámetro, defina y establezca la variable global i! Lamentablemente, SmallBasic no admite parámetros para sus propias subrutinas.

sub animate
for j=0 to Array.getItemCount(i)
for k=0 to Array.getItemCount(i[0])
TextWindow.writeLine(i[j][k])
endfor
Program.delay(9)
TextWindow.clear()
endfor
endsub
Roman Gräf
fuente