Vamos ser animados!


8

O desafio

GIFs são o formato de imagem mais comum para animação e são usados ​​bastante nas mídias sociais atuais. Para o objetivo deste desafio, vou redefinir o que um GIF pode ser. Esse desafio exigirá que você pegue uma matriz 3D que contenha algum tipo de representação de uma 'imagem' 2D e itere através dela, exibindo uma animação. Essa animação pode ser feita em qualquer lugar, em um GIF, no seu console, em uma GUI, etc; a entrega não importa, desde que seja animada.

A entrada

  • Uma matriz 3D onde os dados dentro de alguma forma representam uma imagem 2D.
    • A matriz pode conter dados RGB, dados verdadeiros / falsos ou qualquer outra coisa que você achar melhor.
    • Também estou bem com você modificando-o para uma matriz 2D de seqüências de caracteres ou algo semelhante, mas a animação deve ser uma animação 2D .
  • O tempo entre cada quadro em um formato de sua escolha (segundos, milissegundos, etc ...).
    • As pessoas me perguntam se têm ou não que incluir a duração da duração. Minha resposta é "meh", desde que você seja capaz de mostrar animação. Estou mais preocupado que você adira ao parâmetro "Matriz" do que este, o que significa que não há animações aleatórias.

A saída

  • Uma sequência de saída perfeitamente iterada que se parece com uma animação 2D com o atraso correto em cada transição com base na entrada de valor.

As regras

  • A saída pode ser, mas não está limitada a:
    • Imagem GIF.
    • Animação GUI (meu exemplo).
    • Animação no console.
    • Honestamente, qualquer "animação" que você achar conveniente, desde que siga as regras abaixo.
  • Ao produzir sua imagem, você deve limpar o console antes de mostrar o próximo quadro, não pode imprimi-las apenas sequencialmente.
    • Emular um console "claro" também é aceitável, desde que pareça uma animação contínua (veja a dica no meu exemplo para obter mais informações sobre o que quero dizer).
  • Independentemente da implementação, sua animação deve repetir para sempre ou até parar.
    • O "looping" pode ser tão simples quanto while(true){}uma recursão infinita; você pode assumir que o usuário deseja visualizar esta obra-prima até clicar em "ctrl + c".
  • Você deve poder manipular 'imagens' 2D de qualquer tamanho, se o seu idioma for limitado por tamanhos de buffer, isso é aceitável e você pode declarar isso na sua explicação.
  • As brechas padrão não são permitidas.

Exemplo de E / S

Entrada (matriz 3D, atraso)

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)

Saída (exemplo, 2020 bytes - 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("");
            }
        }
    }
}

Isso resulta em uma GUI de balanço aparecendo, animando a matriz:

Frame One Quadro dois Quadro três

SUGESTÃO: Use um idioma em que a limpeza do console seja possível ou especifique por que o que você está fazendo terminará com um resultado que se parece com uma animação no idioma escolhido. Acho que alguns idiomas têm tamanhos de buffer padrão em seus consoles, você pode usar isso para sua vantagem, mas espero uma explicação ou exemplo. Só porque eu mostro minha animação como uma string, você não precisa; Eu poderia facilmente usar 0 para preto e 1 para branco e criar um GIF real.

A julgar

Isso é código-golfe, menor número de bytes ganhos (entradas excluídas).
Marcarei com +1 qualquer pessoa que use um idioma de uma maneira interessante ou inesperada.


Quantas linhas tem de ser "clara"? Pode ser o mesmo que o número de caracteres por linha?
Riley

Desafio semelhante com a entrada de mais estrito: codegolf.stackexchange.com/questions/27101/...
luser Droog

@Riley Não sei se entendi o que você está perguntando. O claro é essencialmente manter a saída na mesma linha; seu código pode não "limpar" nada, mas substituir na linha também. Não me importo como você realiza a animação, mais do que ela essencialmente funciona usando quadros.
Magic Octopus Urn

@luserdroog Eu não tinha visto esse, mas também vi um em "create a snowscene" também, mas também não vejo o suficientemente perto para justificar a não publicação.
Magic Octopus Urn

1
@carusocomputing Não se preocupe, mais do que feliz em fazer a verificação gramatical. A propósito, em termos de qual idioma é usado para a animação, importa se ele não está mais em uso popular?
Monomeeth 15/09/16

Respostas:


3

MATL , 16 12 11 bytes

`G@)D1Y.XxT

Entrada é uma matriz de células 2D. Por exemplo:

{[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]}

O tempo de pausa é o 1do código. Pode ser alterado para qualquer número real, como .5ou .2.

Experimente no MATL Online! (Se não funcionar, atualize a página e pressione "Executar" novamente.)

A entrada também pode ser uma matriz de células de matrizes de caracteres 2D. Por exemplo:

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

Experimente este também!

Explicação

`       % 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  

1
Você pode salvar alguns bytes usando meu truque? Preencher a matriz com [0.2 0 0.2;0 0.2 0] ... , e assim reduzir xxa x, evitar 1Ge 2G? Eu acredito que adere às regras. Você precisa adicionar alguns bytes para converter 0.2em 1, a menos que queira 0.2pular naturalmente, e alguma maneira de armazenar o valor de pausa. Eu ainda acho que poderia reduzir a contagem de bytes embora :)
Stewie Griffin

1
@Weeingitfirst Thanks! Bem, o desafio especifica duas entradas: a matriz e a pausa, então acho que ambas são necessárias. Vamos esperar a confirmação de qualquer maneira
Luis Mendo

2
Uau. Você seguiu o resumo perfeitamente, até aderindo às informações. Esta é uma resposta muito impressionante. Definitivamente será difícil de bater, e comparado às respostas que não incluíram a duração da pausa, isso é basicamente impecável, bravo.
Magic Octopus Urn

1
@carusocomputing Ótimo! Obrigado por me avisar. 4 bytes de desconto! A duração ainda pode ser alterada, é bastante óbvio no código
Luis Mendo

1
Vou ser sincero, duvido que isso seja superado, então até novas submissões eu vou marcar isso como a melhor resposta.
Magic Octopus Urn

2

Oitava, 56 54 47 bytes

Removida a possibilidade de inserir o tempo de pausa como parte da matriz de entrada. Fiquei muito satisfeito com isso, então dê uma olhada no histórico de edições, se você quiser dar uma olhada. Esta solução é 7 bytes mais curta.

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).

A entrada será mais ou menos assim: [4 0 0 4;0 4 4 0;4 0 0 0]onde será uma matriz de dimensões 3x4 e o tempo de pausa desejado é de 4 segundos.

Ele exibe um gráfico como o abaixo, mas alterna entre mostrar os valores verdadeiro e falso da entrada. Portanto, todos os pontos azuis se tornarão brancos na próxima iteração e todo o branco se tornará azul.

No gráfico abaixo, usei a entrada rand(10,10)>0.6*2 . Isso significa que ele terá dimensões 10x10 e todos os elementos da matriz aleatória maiores que 0,6 serão verdadeiros. Depois disso, multiplico pelo tempo de pausa desejado, 2 segundos. Eu usei uma matriz aleatória aqui, mas também poderia ter criado a matriz manualmente.

Como o Octave não está instalado neste computador, fiz uma pequena alteração para que isso funcionasse no MATLAB. É exatamente o mesmo princípio, mas n=~nnão funciona no MATLAB.

insira a descrição da imagem aqui

insira a descrição da imagem aqui


2
@carusocomputing, tenho que tomar o tempo de pausa como entrada, ou posso escolher eu mesmo? Por exemplo, sempre tem 1 segundo?
Stewie Griffin

1
@carusocomputing, também: está tudo bem deixar o usuário escolher o tempo de pausa, mas não o tem como um parâmetro separado? Na minha não tão humilde opinião, este qualifica como: "um fresco ou forma inesperada" ;-)
Stewie Griffin

1
Sim, eu concordo completamente, isso se qualifica; desde que você permita que o usuário especifique algum parâmetro de entrada e não seja totalmente aleatório, acho que está bem. O objetivo da pausa era poder ver a animação. Eu não queria nenhum loop onde as pessoas afirmam "bem, você não pode vê-lo, mas é definitivamente animado".
Urna Mágica de Polvo

1
Também gostei das duas idéias; o "Gerador estático de TV" foi uma implementação muito única, usando a randomização, que eu nem considerava. Isso também é impressionante, pois você conseguiu fazer a primeira iteração e se aproximar mais do resumo. Ótimo trabalho, cara.
Urna Mágica de Polvo

2

sed 141 134 90

-51 graças a seshoumara

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

Entrada: Primeiro, cada quadro é separado por uma linha com um único espaço e, em seguida, exibe o próximo quadro depois que cada linha em branco é recebida (se parece com um flipbook). Mínimo de 3 quadros.

Por padrão, no meu sistema (Windows 7), quando abro o cygwin, ele tem 24 linhas na vertical. Entre os quadros, sempre há pelo menos muitas linhas em branco impressas. Isso efetivamente limpa a tela.

Mais de 1/3 dos bytes vêm da limpeza do console. Tenho certeza de que há uma maneira melhor.


1
Você pode reduzir 1 byte tendo o primeiro pcomando como parte de s///p, mais 6 bytes removendo /^\n/!antes P, o que acho que não é necessário. Pelo esforço, +1, embora eu também tenha certeza de que há uma maneira melhor.
seshoumara

1
Depois de algum tempo navegando na internet, encontrei uma maneira simples de manipular o cursor do terminal, limpando também uma tela: usando ANSI Escape Sequences. O mecanismo também é usado para imprimir texto em cores. Por favor, veja minha resposta para detalhes e um exemplo de uso. Não sei se eles funcionam no cygwin, mas você pode tentar.
seshoumara

@seshoumara Ele funciona no cygwin quando se trata sed, mas por algum motivo não funciona com catou echo.
Riley

Tente echo -e "\e[2Jtest". Com cat, o caractere de escape já deve estar no arquivo / entrada, tente echo -e "\e[2Jtest"|cat -nrolar para cima.
seshoumara

@seshoumara Eu sabia que tinha que ser algo assim. obrigado!
Riley

2

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

Edit: 3 bytes a menos, graças 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}

O formato de entrada é um quadro de animação por linha. Para várias linhas de saída em um quadro, use vírgula como separador. Como eu executo o programa em um console Linux, o tamanho máximo da imagem disponível (medido em linhas e colunas) depende do tamanho da janela do terminal. A pausa entre dois quadros é realizada pelo comando sleep shell; para receber uma chamada de animação mais 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.

A melhor parte é que eu apoio animação em cores! Para fazer isso, usei as chamadas ANSI Escape Sequences para controlar a fonte do texto, a cor do primeiro plano e do plano de fundo, além da posição do cursor, conseguindo limpar a tela antes de cada quadro (código ESC[2J). Para adicionar informações de cores, use o seguinte formato na entrada, que é melhor explicado aqui .

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

Corre:

sed -nf animate.sed input.txt

Exemplos: para cada teste, 2 ciclos de animação foram capturados na tela e salvos no formato GIF de imagem (desculpas pela baixa resolução)

0,4 segundos de pausa Feliz Aniversário!

1 segundo por padrão movimento "pixel"

Explicação:

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

Você pode salvar alguns bytes substituindo 1h;1d;H;porH;1h;
Riley

@Riley Obrigado, eu atualizei o código.
seshoumara

Uau, isso foi mais profundo do que muitos outros, eu gosto do suporte de cores e é a única resposta que faz isso :). Uso bastante exclusivo de novas linhas também. +1 para suporte de cores e a exclusividade da resposta em si. Honestamente, eu não teria acreditado se não tivesse visto!
Urna Mágica de Polvo

1

Ruby, 89 45 bytes

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

O ^[é um personagem 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)}}

Economizou muitos bytes graças a @Jordan


@DLosc Ah, sim, consertando
TuxCrafting

Você pode salvar muitos bytes aqui. ->h,t{h.cycle{|x|puts"^[[2J",x.map(&:join)}}
Jordânia

Boa resposta, também como FYI, o resumo foi alterado, você não precisa mais aderir à duração como uma entrada, pois isso restringe os possíveis idiomas. Você só precisa fazer uma pausa para que a animação seja 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

Exemplo 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

Saída : https://youtu.be/0kDhPbbyG9E


Hmm, eu não tive muita exposição à lua, eu não sabia que tinha suporte gráfico também, mas sabia que tinha um ótimo desempenho. Uma resposta muito interessante e inesperada. Esta é provavelmente a resposta mais próxima de permitir entrada colorida com base nos números passados. Também a primeira resposta para não usar o ASCII, apesar da alta contagem de bytes, um excelente profissional +1 por exclusividade.
Magic Octopus Urn

1
@carusocomputing Obrigado! O LÖVE é uma estrutura para criar jogos 2D. Você deve dar uma olhada :-)
Master_ex 15/09/16

Oh cara, sério? Você pode me vincular a alguns de seus outros trabalhadores? Eu absolutamente adoraria vê-lo, cara.
Magic Octopus Urn

1

SmallBasic, 167 bytes

Como parâmetro, defina e defina a variável global i! Infelizmente, o SmallBasic não suporta parâmetros para próprias sub-rotinas.

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.