Animar decorações leves bregas

22

Esse desafio é uma homenagem às luzes de Natal brega da casa dos meus sogros.


O desafio é criar uma saída gráfica mostrando a decoração em "tempo real".

O vídeo (gif ou outro formato) terá "luzes" verticais e horizontais n-por-m . 5 <= m, n <= 40 . O tamanho e a resolução de quadro pode variar consoante n e m , mas deve ser, pelo menos, 50x50 pixels para n, m = 5 (gráficos vectoriais é OK). Uma imagem com n=6e m=5será mais ou menos assim:

insira a descrição da imagem aqui


A decoração:

Cores:

Todas as luzes terá um dos 6 RGB-cores seguintes {255,0,0}, {0,255,0}, {0,0,255}, {255,255,0}, {0,255,255}e {255,0,255}.

Animação:

  • ne mserá considerado como entrada em qualquer formato razoável e na ordem que você desejar
  • A imagem mudará a cada dt = 25 ms . Os desvios são válidos se ocorrerem devido a "fatores externos", como limitação no intérprete, computador lento etc.
    • Se for impossível definir a etapa do tempo manualmente, a etapa padrão será aceita.
  • Todas as luzes estarão vermelhas ( {255,0,0}) em t=0.
  • Sempre há uma chance de 5% de que a primeira luz (canto superior esquerdo) mude de cor. Todas as cores (exceto a atual) devem ser igualmente prováveis.
  • Cada luz (exceto a primeira) terá a cor da luz à esquerda. Se a luz estiver na extrema esquerda, ela exibirá a cor da luz na extrema direita na linha acima. As luzes são numeradas como mostrado abaixo. O número da luz kobterá a cor do número da luz k-1.

     1  2  3  4  5  6
     7  8  9 10 11 12
    13 14 15 16 17 18
    
  • Em teoria, a saída deve ser executada para sempre (a menos que seu idioma / intérprete tenha alguma limitação que impeça isso).

  • Forneça uma amostra de pelo menos 5 segundos, de preferência mais na resposta (isso é um incentivo, não um requisito). (Um link para o TIO ou similar também é OK: D)
  • Quadros, eixos, linhas de grade etc são aceitos.

6 por 5

insira a descrição da imagem aqui

15 por 30

insira a descrição da imagem aqui

Stewie Griffin
fonte
Se o intérprete estiver lento, deve-se ajustar o tempo de pausa para que o tempo total entre as atualizações de imagem seja semelhante ao dos exemplos? E se a pausa não for necessária (o código já está lento o suficiente)? Isso economizaria bytes, talvez contra o espírito do desafio
Luis Mendo
1
Como você selecionou as cores para facilitar a implementação - em idiomas como o QBasic que possuem um conjunto limitado de cores interno, é aceitável usar as cores disponíveis mais próximas das que você especificou? (Vermelho, verde, azul, amarelo, ciano, magenta)
DLosc 29/12/16
Se for impossível usar as cores especificadas, sim, não há problema em usar as alternativas mais próximas. Se é só um pouco mais, então não. r,g,y,b,etc são mais curtos em vários idiomas.
Stewie Griffin
@LuisMendo, desculpas pela resposta tardia. Eu gosto do jeito que você fez na sua resposta. Seria bom usar 25 ms, mesmo que isso tornasse a animação mais lenta. Evitei drawnowquando implementei isso no MATLAB, pois o resultado foi muito lento. Eu acho que a resposta deve ser: Se for uma opção de design que o intérprete tenha uma resolução de tempo mínimo fixa de> = 25 ms, tudo bem. Se for devido a uma implementação ruim / simples, um intérprete on-line sobrecarregado / lento etc., não está correto.
Stewie Griffin
1
@ Stewie Entendi, obrigado. E bom desafio!
Luis Mendo

Respostas:

6

JavaScript / CSS / HTML, 436 bytes

b="red"
f=_=>{o.textContent='';o.style.width=w.value*10+"px";o.style.height=h.value*10+"px"}
setInterval(_=>o.insertBefore(document.createElement("s"),o.firstChild).style.background=b=["red","yellow","lime","aqua","blue","fuchsia"][Math.random()*100|0]||b,25)
#o{overflow:hidden;background:red}s{display:block;float:left;width:10px;height:10px}
<div oninput=f()><input id=h type=number min=1><input id=w type=number min=1></div><div id=o>

Neil
fonte
6

Mathematica, 186 161 158 bytes

(b=Table[{1,0,0},1##];Dynamic@Image[Partition[[email protected];If[Random[]<.06,b[[1]]={1,1,0,0}~RandomSample~3];b=RotateRight@b;b[[1]]=b[[2]];b,#],ImageSize->50#])&

Explicação

b=Table[{1,0,0},1##];

Crie o quadro inicial em 1D, preenchido com vermelho. Armazene isso em b.

[email protected]

Pausa por 25ms

If[Random[]<.06,b[[1]]={1,1,0,0}~RandomSample~3]

Se um número real aleatório (pseudo-) for menor que 0,06, substitua o primeiro elemento bpor um comprimento 3de amostra aleatório da lista {1,1,0,0}. (ou seja, qualquer um {1, 1, 0}, {1, 0, 1}, {1, 0, 0}, {0, 1, 1}, {0, 1, 0}, {0, 0, 1})

b=RotateRight@b

Cíclico gire para a direita.

b[[1]]=b[[2]]

Altere o valor da primeira célula para o valor da segunda célula (ou seja, desfaça o deslocamento da primeira célula)

Partition[ ... ;b,#]

Partição bem (altura).

Dynamic@Image[ ... ,ImageSize->50#]

Transforme isso em uma imagem dinâmica (atualizando constantemente), cuja largura é 50 (largura)

Versão de autômato celular (186 bytes)

(b=Table[{1,0,0},1##];Dynamic@Image[Partition[[email protected];If[Random[]<.06,b[[1]]={1,1,0,0}~RandomSample~3];i=2;b={#[[2-Boole[i--<0],2]]&,{},{1,1}}~CellularAutomaton~b,#],ImageSize->50#])&

Saída de amostra (entradas: 16, 10)

insira a descrição da imagem aqui

JungHwan Min
fonte
6

MATLAB, 255 210 bytes

Este é o meu primeiro golfe, então provavelmente há melhorias a serem feitas.

Obrigado ao Luis por me ajudar a salvar 45 bytes :)

function f(n,m)
c=dec2bin(1:6)-48;r=1;p=c(r,:);x=zeros(1,n*m,3);x(:,:,1)=1;while 1
x=circshift(x,[0,1,0]);if rand>0.94;r=randi(6);end
x(1,1,:) = c(r,:);imagesc(permute(reshape(x,n,m,3),[2 1 3]));pause(1/40);end

Explicação:

c=dec2bin(1:6)-48  % c is the colormap
r=1;p=c(r,:);                % p is color number r (starting at 1) from the colormap c
x=zeros(1,n*m,3);x(:,:,1)=1; % 2D matrix in the third dimension. The first layer is 1
while 1                      % while true
x=circshift(x,[0,1,0]);      % shift the vector horizontally along the second dimension
if rand()>0.94;              % 5 percent chance of changing color
k=randperm(6);k=k(k~=r);r=k(1); % Create a vector with color numbers 1..6. Discard the current color, and choose the first color
x(1,1,:) = c(r,:);           % The first light gets color number r
imagesc(permute(reshape(x,n,m,3),[2 1 3]));  % Reshape the vector so that it's a 3D matrix
% Permute it so that the dimensions are correct
% Use imagesc to display
pause(1/40)  % 0.025 seconds pause

Infelizmente, isso não salva a animação, apenas a executa. Para salvá-lo, preciso de um programa de captura de tela ou reescrever tudo usando imwrite. Em vez disso, fornecerei duas fotos mostrando horários diferentes, por n=15,m=30.

insira a descrição da imagem aqui

insira a descrição da imagem aqui

CG.
fonte
1
Algumas sugestões de golfe: em dec2bin([4 2 1 6 3 5])-48vez de [1 0 0;0 1 0;0 0 1;1 1 0; 0 1 1;1 0 1]. .95em vez de 0.95. Você também pode substituir .95por .94e livrar-se k=k(k~=r);(porque 0,94 + 0,06 / 6 = 0,95; ver a minha resposta para uma explicação mais detalhada)
Luis Mendo
1
Melhor ainda, c=dec2bin(1:6)-48como a ordem não importa #
Luis Mendo 30/12
Ótima primeira resposta! No entanto, receio ter superado você em 40% .
Sanchises
Golpeou um pouco :) Obrigado pela ajuda Luis. ! :) Sanchises bem feito!
CG.
4

MATL , 52 47 bytes

6:BoHZGKipY"`tGe!2YG50Yr3>?t1)}6Yr]0(1YS.015Y.T

Entrada é uma matriz [ncols nrows]. Saída é uma figura com gráficos vetoriais.

Exemplo de execução para 15 colunas × 10 linhas:

insira a descrição da imagem aqui

Como funciona

O tempo de pausa foi definido como 15 ms (para a mesma contagem de bytes de 25 ms) para tentar compensar o tempo de processamento.

Para manter a cor com probabilidade 19/20 (altere com 1/20), procedemos da seguinte maneira:

  • Com probabilidade de 47/50, mantemos a cor.
  • Com probabilidade de 3/50, escolhemos uma nova cor escolhida uniformemente entre as 6 cores. Pode acontecer que a "nova" cor seja igual à antiga, e isso ocorre com probabilidade 1/6.

Assim, a probabilidade de manter a cor é 47/50 + 3 / (50 * 6) = 19/20.

6:        % Push [1 2 3 4 5 6]
B         % Convert to binary. This gives a 6×3 matrix, where each row 
          % corresponds to a number. First row is [0 0 1] (blue), second is
          % [0 1 0] (green), etc
o         % Convert to double
HZG       % Set as colormap (creates a figure)
K         % Push 4
i         % Take input array
p         % Product of array. This gives the total number of squares
Y"        % Repeat 4 that many times. This gives a row vector representing the
          % image. The initial value, 4, corresponds to red in the colormap
`         % Do...while
  t       %   Duplicate
  Ge      %   Reshape to size given by the input. Gives a matrix where each
          %   entry  will be interpreted as a pointer to the colormap
  !       %   Transpose. This is required because the color shifting will be
          %   done in column-major order: down, then across; whereas we want
          %   the opposite
  2YG     %   Show matrix as image using the defined colormap
  50Yr    %   Push a uniformly distributed random integer between 1 and 50
  3>      %   True if greater than 3. This happens with probability 47/50
  ?       %   If true
    t1)   %     Duplicate and get first entry (to repeat the first color)
  }       %   Else
    6Yr   %     Push a uniformly distributed random integer between 1 and 6.
          %     This is the new color (possibly the same as the old)
  ]       %   End
  0(      %   Assign that color (repeated or new) to the last entry of the row
          %   vector representing the image
  1YS     %   Circularly shift to the right. The last value becomes the first
 .015Y.   %   Pause 0.015 ms
 T        %   Push true
          % End (implicit). Since the top of the stack is true, this creates
          % an infinite loop
Luis Mendo
fonte
3

MATLAB, 153 147 bytes

Nota : O GIF mostrado é da versão mais antiga, o que é bom, pois não exibe eixos (consulte o histórico de edições), mas foi extremamente lento devido à implementação de imshow. Para a versão atual, a resposta MATLAB de Chelsea G. ou MATL de Luis Mendo mostra o mesmo resultado que minha versão atual.

O tamanho é tomado como um 2x1vetor, então chame como por exemplo:

>> l([5 5])

function l(s)
c=eye(3);x=eye(s);while 1
a=rand>.94;x=[a*randi(6)+~a*x(1),x(1:end-1)];imagesc(reshape(x,s)',[1,6]);colormap([c;1-c])
pause(.025)
end

Esta resposta explora as sutilezas da linguagem MATLAB. Por exemplo, xé inicializado como uma m x nmatriz zero, mas a chamada indexação linear permite deslocamento circular com índices unidimensionais. A digitação fraca permite a multiplicação com elementos lógicos, para que as ifinstruções sejam evitadas (um truque que eu costumava usar nos dias de programação em uma calculadora TI-84). Embora um mapa de cores seja lido em linhas, o MATLAB o trata como uma matriz normal, de modo que eye(3)pode ser usado para criar vermelho, verde e azul e 1-eye(3)as outras três cores. Um simples reshapetraz o vetor linear de volta à forma de matriz, que é mapeada para as cores desejadas usandoind2rgb . Finalmente,imagesc, mostra a imagem, mostrada no tamanho padrão da figura (que é grande o suficiente para os requisitos). Como ele teria sorte, imagescnão se importa de valores que são fora do intervalo especificado, por isso eyepode ser usado para inicializar a matriz uma vez que ambos 1e 0são considerados vermelho.

insira a descrição da imagem aqui

Sanchises
fonte
1
Opa, esqueci de te votar ... Eu amo todos os seus pequenos truques :-)
CG.
É correto que a cor aleatória nunca seja vermelha na versão atualizada? Aparece dessa forma no Octave pelo menos (não possui MATLAB).
Stewie Griffin 16/03
@StewieGriffin Devo estar dormindo quando fiz isso. Claro que você está perfeitamente certo - e também me salvou um byte ...
Sanchises 17/03
(crie esses dois bytes)
Sanchises 17/03
2

Python 3.6 (316 bytes)

Usando códigos de cores ANSI e os novos literais de string formatados do Python 3.6 ( PEP 489 ) (a f"{X}"mágica).

Caso contrário, é apenas bastante básico, mas python ofuscado. Largura e Altura são passados ​​como argumentos na linha de comando.

import random as n,time,sys
r=range
X="\x1b["
C=[f"{X}1;4{x}m " for x in r(1,7)]
w,h=list(map(int,sys.argv[1:]))
a=[C[0]for i in r(w*h)]
while 1:
 print(f"{X}0m{X}2J{X}f");f=a[0];a.pop();a[:0]=n.choice([x for x in C if x!=f])if n.random()<=.05 else f,
 for i in r(0,h*w,w):print(*a[i:i+w],sep="")
 time.sleep(.025)

insira a descrição da imagem aqui

Jonas Schäfer
fonte
Você pode poupar 6 bytes usando w,h=map(int,sys.argv[1:]), descompactar funciona com qualquer iterável (do tamanho certo), a chamada para a lista é supérflua.
Sebastian Riese
Mais alguns bytes invertidos: "\x1b["=> "\33["(usando octal em vez de hexadecimal), a abreviação X e as seqüências de caracteres de formato realmente a tornam mais longa (e se livrar de f""você obtém compatibilidade com qualquer python3). (isso reduzirá para 301 bytes).
Sebastian Riese
Opa, você usa {x}uma vez ... mas você ainda ganha ao se livrar X.
Sebastian Riese