Animar decoraciones de luz pegajosa

22

Este desafío es en honor a las horteras luces navideñas en la casa de mis suegros.


El desafío es crear una salida gráfica que muestre la decoración en "tiempo real".

El video (gif u otro formato) tendrá "luces" verticales y horizontales n-por-m . 5 <= m, n <= 40 . El tamaño de imagen y resolución pueden variar dependiendo de n y m , pero deben ser al menos de 50x50 píxeles para n, m = 5 (gráficos vectoriales es OK). Una imagen con n=6y m=5se verá más o menos así:

ingrese la descripción de la imagen aquí


La decoración:

Colores:

Todas las luces tendrán una de las siguientes 6-colores RGB {255,0,0}, {0,255,0}, {0,0,255}, {255,255,0}, {0,255,255}y {255,0,255}.

Animación:

  • ny mse tomará como entrada en cualquier formato razonable y en el orden que desee
  • La imagen cambiará cada dt = 25 ms. Las desviaciones están bien si se debe a "factores externos" como la limitación en el intérprete, la computadora lenta, etc.
    • Si es imposible establecer el paso de tiempo manualmente, entonces se acepta el paso de tiempo predeterminado.
  • Todas las luces serán rojas ( {255,0,0}) en t=0.
  • Siempre hay un 5% de posibilidades de que la primera luz (arriba a la izquierda) cambie de color. Todos los colores (excepto el color que tiene actualmente) deberían ser igualmente probables.
  • Cada luz (excepto la primera) obtendrá el color de la luz a su izquierda. Si la luz está en el extremo izquierdo, obtendrá el color de la luz en el extremo derecho en la fila de arriba. Las luces están numeradas como se muestra a continuación. El número de luz kobtendrá el color del número de luz k-1.

     1  2  3  4  5  6
     7  8  9 10 11 12
    13 14 15 16 17 18
    
  • En teoría, el resultado debería ejecutarse para siempre (a menos que su idioma / intérprete tenga alguna limitación que lo impida).

  • Proporcione una muestra de al menos 5 segundos, preferiblemente más en la respuesta (esto es un estímulo, no un requisito). (Un enlace a TIO o similar, por supuesto, también está bien: D)
  • Se aceptan marcos, ejes, líneas de cuadrícula, etc.

6 por 5

ingrese la descripción de la imagen aquí

15 por 30

ingrese la descripción de la imagen aquí

Stewie Griffin
fuente
Si el intérprete es lento, ¿debe ajustarse el tiempo de pausa para que el tiempo total entre actualizaciones de imágenes sea similar al de los ejemplos? ¿Qué pasa si la pausa no es necesaria (el código ya es lo suficientemente lento)? Eso ahorraría bytes, tal vez contra el espíritu del desafío
Luis Mendo
1
Dado que eligió los colores para facilitar la implementación, en lenguajes como QBasic que tienen un conjunto limitado de colores incorporados, ¿es aceptable usar los colores disponibles más cercanos a los que especificó? (Rojo, verde, azul, amarillo, cian, magenta)
DLosc
Si es imposible usar los colores especificados, entonces sí, está bien usar las alternativas más cercanas. Si es solo un poco más, entonces no. r,g,y,b,etc son más cortos en varios idiomas.
Stewie Griffin
@LuisMendo, disculpas por la respuesta tardía. Me gusta cómo lo hiciste en tu respuesta. Estaría bien usar 25 ms, incluso si eso haría que la animación fuera más lenta. Lo evité drawnowcuando implementé esto en MATLAB, ya que el resultado fue demasiado lento. Creo que la respuesta debe ser: si es una elección de diseño que el intérprete tenga una resolución de tiempo mínima fija de> = 25 ms, entonces está bien. Si se debe a una implementación pobre / simple, un intérprete en línea que está sobrecargado / lento, etc., entonces no está bien.
Stewie Griffin
1
@Stewie Lo tengo, gracias. Y bonito desafío!
Luis Mendo

Respuestas:

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
fuente
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#])&

Explicación

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

Crea el tablero inicial en 1D, lleno de rojo. Almacene eso en b.

[email protected]

Pausa de 25 ms

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

Si un número real (pseudo-) aleatorio es menor que 0.06, reemplace el primer elemento de bcon una longitud 3de muestra aleatoria de la lista {1,1,0,0}. (es decir, cualquiera de {1, 1, 0}, {1, 0, 1}, {1, 0, 0}, {0, 1, 1}, {0, 1, 0}, {0, 0, 1})

b=RotateRight@b

Cíclico rotar a la derecha.

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

Cambie el valor de la primera celda al valor de la segunda celda (es decir, deshaga el desplazamiento de la primera celda)

Partition[ ... ;b,#]

Partición ben (altura).

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

Conviértalo en una imagen dinámica (en constante actualización), cuyo ancho es 50 (ancho)

Versión de autómata 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#])&

Salida de muestra (entradas: 16, 10)

ingrese la descripción de la imagen aquí

JungHwan Min
fuente
6

MATLAB, 255 210 bytes

Este es mi primer golf, por lo que probablemente haya mejoras por hacer.

Gracias a Luis por ayudarme a ahorrar 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

Explicación:

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

Desafortunadamente, esto no guarda la animación, solo la ejecuta. Para guardarlo, necesito un programa de captura de pantalla o lo reescribo todo usando imwrite. En cambio, proporcionaré dos imágenes que muestran tiempos diferentes, para n=15,m=30.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

CG
fuente
1
Algunas sugerencias de golf: en dec2bin([4 2 1 6 3 5])-48lugar de [1 0 0;0 1 0;0 0 1;1 1 0; 0 1 1;1 0 1]. .95en lugar de 0.95. También puede reemplazar .95por .94y deshacerse de k=k(k~=r);(0,94 + 0,06 porque / 6 = 0,95; ver mi respuesta para una explicación más detallada)
Luis Mendo
1
Mejor aún, c=dec2bin(1:6)-48como el orden no importa
Luis Mendo
Buena primera respuesta! Sin embargo, me temo que te he superado en un 40% .
Sanchises
Golfed un poco :) Gracias por la ayuda Luis. ! :) Bien hecho Sanchises!
CG.
4

MATL , 52 47 bytes

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

La entrada es una matriz [ncols nrows]. La salida es una figura con gráficos vectoriales.

Ejemplo ejecutado para 15 cols × 10 filas:

ingrese la descripción de la imagen aquí

Cómo funciona

El tiempo de pausa se ha establecido en 15 ms (para el mismo número de bytes que 25 ms) para intentar compensar el tiempo de procesamiento.

Para mantener el color con una probabilidad de 19/20 (cámbielo con 1/20), procedemos de la siguiente manera:

  • Con una probabilidad de 47/50, mantenemos el color.
  • Con una probabilidad de 3/50, elegimos un nuevo color elegido uniformemente entre los 6 colores. Puede suceder que el color "nuevo" sea el mismo que el anterior, y esto ocurre con probabilidad 1/6.

Por lo tanto, la probabilidad de mantener el color es 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
fuente
3

MATLAB, 153 147 bytes

Nota : El GIF que se muestra es de la versión anterior, lo cual es bueno ya que no muestra ejes (ver el historial de edición), pero fue extremadamente lento debido a la implementación de imshow. Para la versión actual, la respuesta MATLAB de Chelsea G. o la respuesta MATLAB de Luis Mendo muestran el mismo resultado que mi versión actual.

El tamaño se toma como un 2x1vector, así que llame como, por ejemplo:

>> 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 respuesta explota las sutilezas del lenguaje MATLAB. Por ejemplo, xse inicializa como una m x nmatriz cero, pero la denominada indexación lineal permite el desplazamiento circular con índices unidimensionales. La escritura débil permite la multiplicación con lógica, por lo que ifse evitan las declaraciones (un truco que utilicé mucho en los días de programación en una calculadora TI-84). Aunque un mapa de colores se lee en hileras, MATLAB lo trata como una matriz normal, de modo que eye(3)se puede usar para crear rojo, verde y azul, y 1-eye(3)los otros tres colores. Un simple reshapedevuelve el vector lineal a la forma de matriz, que se asigna a los colores deseados utilizando ind2rgb. Finalmente,imagesc, muestra la imagen, que se muestra con el tamaño de figura predeterminado (que es lo suficientemente grande para los requisitos). La suerte quiso que imagescno le importa valores que se están fuera del rango especificado, por lo que eyese puede utilizar para inicializar la matriz, ya que ambos 1y 0son considerados rojo.

ingrese la descripción de la imagen aquí

Sanchises
fuente
1
Vaya, olvidé votarte ... Me encantan todos tus pequeños trucos :-)
CG.
¿Es correcto que el color aleatorio nunca sea rojo en la versión actualizada? Parece de esa manera en Octave al menos (no tiene MATLAB).
Stewie Griffin
@StewieGriffin Debo haber estado durmiendo cuando hice esto. Por supuesto que tiene toda la razón, y también me salvó un byte ...
Sanchises
(hacer esos dos bytes)
Sanchises
2

Python 3.6 (316 Bytes)

Usando códigos de color ANSI y los nuevos literales de cadena formateados de Python 3.6 ( PEP 489 ) (la f"{X}"magia).

De lo contrario, es bastante básico, pero Python ofuscado. Ancho y Altura se pasan como argumentos en la línea 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)

ingrese la descripción de la imagen aquí

Jonas Schäfer
fuente
Puede ahorrar 6 bytes mediante el uso w,h=map(int,sys.argv[1:]), desempaquetar funciona con cualquier iterable (del tamaño correcto), la llamada a la lista es superflua.
Sebastian Riese
Otros pocos bytes hacia abajo: "\x1b["=> "\33["(usando escapes octales en lugar de hexadecimales), luego la abreviatura X y las cadenas de formato en realidad lo hacen más largo (y al deshacerse de f""usted obtendrá compatibilidad con cualquier python3). (Esto lo reducirá a 301 bytes).
Sebastian Riese
Vaya, lo usas {x}una vez ... pero aún así ganas al deshacerte de él X.
Sebastian Riese