Un embotellamiento 2D

17

El modelo de tráfico Biham-Middleton-Levine es un autómata celular autoorganizado que modela el tráfico simplificado.

Consiste en una cantidad de automóviles representados por puntos en una red con una posición de inicio aleatoria, donde cada automóvil puede ser uno de dos tipos: aquellos que solo se mueven hacia abajo (se muestra en azul en este artículo) y aquellos que solo se mueven hacia el derecha (se muestra en rojo en este artículo). Los dos tipos de automóviles se turnan para moverse. Durante cada turno, todos los autos para el tipo correspondiente avanzan un paso si no están bloqueados por otro auto.

Su tarea es visualizar este modelo como una animación. Aquí hay algunas buenas demostraciones.

ingrese la descripción de la imagen aquí

Entrada

Un número de coma flotante entre 0 y 1 que representa la densidad, y dos enteros que representan la altura y el ancho de la cuadrícula mostrada. Suponga que las entradas son válidas y que los parámetros para una función o lectura de entrada del usuario están bien.

Ejemplo: 0.38 144 89(corresponde a la imagen de arriba)

Salida

Una cuadrícula, al menos 80x80, que muestra la animación de este modelo en ejecución. Al principio, los autos se colocan aleatoriamente en la cuadrícula hasta que la cuadrícula alcanza la densidad de entrada, con mitad rojo y mitad azul (es decir, densidad multiplicada por el número total de cuadrados de la cuadrícula, redondeados como desee). La densidad debe ser este valor, lo que significa que no puede llenar cada celda con densidad como una probabilidad. Para cada paso, un tipo de automóvil se mueve hacia abajo o hacia la derecha, envolviéndose si pasan el borde. El tipo de automóvil que se mueve alterna cada paso. Para que la animación sea visible, debe haber al menos 10 ms entre cada paso.

Reglas

  • Los automóviles pueden ser de cualquier color o símbolo, siempre que sean distinguibles entre sí y del fondo, y cada tipo de automóvil sea del mismo color o símbolo.

  • La consola y la salida gráfica están permitidas. Para la salida de la consola, cualquier símbolo imprimible está bien, pero la salida debe ser como una cuadrícula de caracteres.

  • Especifique qué tipo de salida ha producido si no tiene una captura de pantalla o gif.

  • La simulación debe ejecutarse para siempre.

El resultado es un poco complejo, así que si tiene alguna pregunta, por favor comente.

qwr
fuente
¿Alguna restricción sobre qué tan lenta o rápida debe correr la animación?
xnor
Quizás valga la pena especificar que el tipo de automóvil que se mueve alterna cada paso.
Greg Martin
@xnor Estaba pensando al menos 5 o 10 ms por ciclo, pero no estoy realmente seguro de si eso sería difícil de medir.
qwr
3
¿La densidad significa que la densidad tiene que ser ese valor, o simplemente que cada píxel tiene una probabilidad d de ser llenado? Además, ¿tenemos que asignar el color de los autos al azar o no? Si al azar, de nuevo, ¿está bien si solo tienen una probabilidad de 50-50 de ser de cualquier color?
JAD
1
@JarkoDubbeldam La densidad tiene que ser ese valor. Tienen una probabilidad de 50-50 de ser de cada color. Sin embargo, respondí tarde, así que las respuestas pueden ser diferentes. Los autos pueden moverse hacia arriba o hacia la izquierda.
qwr

Respuestas:

5

R, 350 338 293 291 273 268 264 bytes

function(d,x,y){f=function(w){v=length(w);for(j in which(w>0&!w[c(2:v,1)]))w[c(j,j%%v+1)]=0:1;w};m=matrix(sample(c(rep(1,q<-floor(d*y*x/2)),rep(-1,q),rep(0,x*y-2*q))),x);p=animation::ani.pause;o=image;a=apply;repeat{o(m<-t(a(m,1,f)));p();o(m<--1*a(-1*m,2,f));p()}}

Sin golf:

function(d,x,y){
  q=floor(d*y*x/2)

  m=matrix(sample(c(rep(1,q),rep(-1,q),rep(0,x*y-2*q))),x)

  f=function(w){
    v=length(w)
    for(j in which(w>0&!w[c(2:v,1)])){
      w[c(j,j%%v+1)]=0:1
    }
    w
  }


  library(animation)
  repeat{
    m=t(apply(m,1,f))
    image(m)
    m=-1*apply(-1*t(m),2,f))
    ani.pause()
    image(m)  
    ani.pause()
  }
}

Función que toma 3 argumentos: d como densidad, y dimensiones x,y. qes la cantidad de autos en cada color. mes la matriz con los automóviles, que inicialmente se llena tomando un tipo aleatorio del número de automóviles y espacios vacíos. Los autos son 1o -1, el espacio vacío es 0.

fes una función que mueve los autos una fila, mirando los autos codificados como 1. Comprueba si el coche puede moverse comprobando si hay 1s seguido de 0. Solíamos applycorrer fen cada fila o columna, dependiendo de qué automóviles.

fmaneja el movimiento de los 1automóviles, para mover los -1automóviles, transponemos la matriz, cambiando la dirección del movimiento, multiplicando la matriz por -1, para que los -1automóviles se vuelvan1 automóviles, y vv y la matriz resultante se transforma nuevamente.

Esto se usa imagepara crear la gráfica, usando 3 colores predeterminados para los tres valores. Utiliza el animationpaquete para manejar las animaciones usando las opciones predeterminadas, que es 1 fps.

0.38, 144, 89:

Enlace a GIF

0.2, 144, 89:

Enlace a GIF

0.53, 144, 89:

Enlace a GIF

JAD
fuente
Su animación se ve realmente genial, ¿qué densidad usó? Parece que todo se atascó bastante rápido con mucho espacio vacío
qwr
@qwr que en realidad era algo que me estaba molestando. En mi programa, todo se atasca a densidades más bajas que en el ejemplo que vinculaste. Sin embargo, no puedo recordar los parámetros exactos utilizados para la trama, pero podría muy bien ser el 0.38 144 89del ejemplo.
JAD
Jugando con cuadrículas cuadradas obtuve una densidad de 0.35 para atascar jasondavies.com/bml/#0.35/100/100 pero casi siempre es una línea gruesa de 45 grados en lugar de líneas diagonales delgadas. Dado que sus líneas se ven más verticales, creo que algo con los dos tipos de automóviles está apagado
qwr
Ahora veo el problema. Cara solo puede avanzar si no los bloquea otro automóvil. Entonces, en los ejemplos de Wikipedia, todos los automóviles en movimiento tienen un espacio frente a ellos. Pero en tu animación los autos se mueven como una línea. Interesante.
qwr
Ah, eso lo haría.
JAD
5

Mathematica, 237 228 203 198 181 bytes

(b=RandomSample@ArrayReshape[Table[{0,i=2},##/2],{1##2},1]~Partition~#2;Dynamic@Colorize[i=-i;b=CellularAutomaton[{193973693,{3,{a=0{,,},{3,9,1},a}},{1,1}},b];If[i>0,b,2-b]])&

La salida es una dinámica Image. El fondo es de color verde claro, y los autos son negros o magenta, dependiendo de su dirección.

Explicación

b=RandomSample@ArrayReshape[Table[{i=1,2},##/2],{1##2},1]~Partition~#2

Crea el tablero inicial:

Table[{0,i=2},##/2]

Establecer ia 2. Cree un Listde {0, 2}, cuya longitud es piso (densidad * ancho * alto / 2) (dividido entre dos porque {0, 2}es longitud-2).

ArrayReshape[ ... ,{1##2},1]

Cambie la forma del 2-D resultante List(2 x algo) en 1-D List(largo = ancho * alto). Rellene 1si no hay suficientes valores.

RandomSample@ ...

(Pseudo-) ordena aleatoriamente el resultado.

... ~Partition~#2

Partición que resulta en longitud (ancho).

b= ...

Almacenar eso en b .


Dynamic@Colorize[i=-i;b=CellularAutomaton[{193973693,{3,{a=0{,,},{3,9,1},a}},{1,1}},b];If[i>0,b,2-b]]

Crear un Dynamic Image :

i=-i;

Voltear el signo de i.

b=CellularAutomaton[{193973693,{3,{a=0{,,},{3,9,1},a}},{1,1}},b]

Aplique el autómata celular con regla 193973693y pesos vecinos {{0, 0, 0}, {3, 9, 1}, {0, 0, 0}}a btranspuesto. Conjuntob igual a eso.

If[i>0,b,2-b]

Si ies positivo, déjalo bsolo. Si no, transponga el b( 2-está allí porque jugué CellularAutomatonun poco al golf ). Esencialmente, esto transponeb cualquier otra iteración (para deshacer la transposición)

Colorize[ ... ]

Convierta la matriz en un colorido Image .

Dynamic@ ...

Hacer la expresión Dynamic . es decir, las funciones anteriores se ejecutan repetidamente.

Salida

Aquí hay una salida de muestra (entradas: 0.35, 192, 108 para 2000 cuadros (magnificados 2x).

https://i.imgur.com/zmSyRut.mp4

JungHwan Min
fuente
¿Eh, usar el incorporado es más largo que no usarlo?
Adám
3

Dyalog APL , 190 108 115 112 bytes

Solución

S←{⍉⍣⍺⊢d[⍺]↑d[⍺]↓⍉↑(⍺⊃'(↓+) ' '(→+) ')⎕R' \1'↓(,⍨,⊢)⍉⍣⍺⍉⎕←⍵⊣⎕DL÷4}
{1S 0S⍵}⍣≡' ↓→'[d⍴{⍵[?⍨⍴⍵]}c1 2⍴⍨⌊⎕×c←×/d←⎕]

TryAPL en línea (ligeramente modificado debido a restricciones en línea):

  1. Set ⎕IO←0, definir la función S , y luego definir y mostrar una al azar 38% 14 × 29 cuadrícula, G .

  2. Haz un movimiento hacia abajo.

  3. Haz un movimiento a la derecha.

  4. Ve al paso 2.

    Tráfico
    Animación del algoritmo anterior, que no garantizaba la densidad.

Explicación

S←{defina la función directa S (explicada aquí de derecha a izquierda):

÷4 recíproco de 4 (0.25)

⎕DL esperar tantos segundos (devuelve el tiempo transcurrido real)

⍵⊣ descartar eso a favor de ⍵ (el argumento correcto; la cuadrícula)

⎕← salida que

 transponer

⍉⍣⍺ transponer de nuevo si ⍺ (el argumento izquierdo; 0 = abajo, 1 = derecha)

( aplique el tren de funciones (explicado aquí de izquierda a derecha):

  ,⍨ el argumento adjunto a sí mismo

  , anexado a

   sí mismo

)

 dividir la matriz en una lista de listas

( buscar expresiones regulares (explicado aquí de izquierda a derecha):

  ⍺⊃ elija uno de los dos siguientes en función de 0 (0 = abajo / primero, 1 = derecha / segundo)

  '(↓+) ' '(→+) ' secuencias de flecha hacia abajo y hacia la izquierda seguidas de un espacio

)⎕R' \1' reemplazar con un espacio seguido de la secuencia encontrada

 mezclar lista de listas en matriz

 transponer

d[⍺]↓ soltar filas de "altura" si ⍺ (argumento izquierdo) es 0 (abajo) o filas de "ancho" si ⍺ es 1 (derecha)

d[⍺]↑ luego toma tantas filas

 pasar a través (sirve como separador)

⍉⍣⍺ transponer si ⍺ (el argumento izquierdo; 0 = abajo, 1 = derecha)

}


' ↓→'[ indexe la cadena con (explicada aquí de derecha a izquierda):

 entrada numérica (dimensiones)

d← asignar eso a d

×/ multiplica las dimensiones (encuentra el recuento de celdas)

c← asignar eso a c

⎕× multiplique eso con entrada numérica (la densidad)

 redondear a la baja

1 2⍴⍨ repetir cíclicamente uno y dos hasta esa longitud

c↑ extiéndalo hasta la longitud c , rellenando con ceros

d⍴ use d (las dimensiones) para remodelar

{ aplique esta función anónima a eso (explicado aquí de izquierda a derecha):

  ⍵[ El argumento correcto (la lista de ceros, unos y dos) indexado por

   ?⍨ los índices barajados hasta

   ⍴⍵ la longitud del argumento

  ]

}

]

{ aplique la siguiente función anónima (explicada de derecha a izquierda):

0S⍵ aplique S con 0 (abajo) como argumento izquierdo y la cuadrícula como argumento derecho

1S con eso como argumento correcto, aplique S con 1 (derecho) como argumento izquierdo

}⍣≡ hasta que dos iteraciones sucesivas sean idénticas (un atasco de tráfico)

Notas

  1. Requiere ⎕IO←0, que es el predeterminado en muchos sistemas.

  2. Solicita (alto, ancho) y luego densidad.

  3. No utiliza ningún autómata incorporado.

  4. Utiliza soporte de expresiones regulares incorporado.

  5. Se detiene si hay un atasco (ningún automóvil puede moverse).

  6. Emite matrices de caracteres donde representa los automóviles que se mueven hacia la derecha, representa los automóviles que se mueven hacia abajo y los espacios son carreteras vacías.

  7. Como arriba, sale a la sesión a 4 Hz, pero la frecuencia se puede ajustar cambiando ÷4; por ejemplo, ÷3es 3 Hz y .3es ³⁄₁₀ Hz.

  8. Es más fácil ver qué sucede si se ejecuta ]Box on -s=max -f=onprimero.

  9. La distribución requerida ahora está garantizada, y los dos tipos de automóviles se producen exactamente en 50-50, salvo el redondeo.

Adán
fuente
Su generación de placa inicial no garantiza una placa que tenga la densidad de entrada. Supongo que es la opción de OP si permitir eso o no.
JungHwan Min
Oh, @JarkoDubbeldam ya preguntó eso.
JungHwan Min
@JungHwanMin ¿Cómo es eso? Deje que la densidad sea d. Cada posición recibe un valor entre 0 y 1. Si entre 0 y se convierte en un ᵈ/₂ ,. Si entre ᵈ⁄₂ yd se convierte en a . Si entre d y 1 se queda vacío.
Adám
Bueno, un caso extremo sería: cada posición de alguna manera obtiene el valor 0 (porque son (pseudo) generados aleatoriamente (pseudo) de forma independiente; muy improbable pero posible). Entonces tu tablero está lleno de s.
JungHwan Min
@JungHwanMin Ah, entiendo lo que quieres decir.
Adám
1

Java (624 bytes + 18 bytes para Java.awt. * = 642 bytes)

static void k(double b,final int c,final int d){final int[][]a=new int[c+1][d+1];int i=0,j;for(;i<c;i++){for(j=0;j<d;j++){a[i][j]=Math.random()<b?Math.random()<0.5?1:2:0;}}Frame e=new Frame(){public void paint(Graphics g){setVisible(1>0);int i=0,j;for(;i<c;i++){for(j=0;j<d;j++){g.setColor(a[i][j]==2?Color.BLUE:a[i][j]==1?Color.RED:Color.WHITE);g.drawLine(i,j,i,j);}}for(i=c-1;i>=0;i--){for(j=d-1;j>=0;j--){if(a[i][j]==1&&a[i][(j+1)%d]==0){a[i][(j+1)%d]=1;a[i][j]=0;}else if(a[i][j]>1&&a[(i+1)%c][j]==0){a[(i+1)%c][j]=2;a[i][j]=0;}}}}};e.show();while(1>0){e.setSize(c,d+i++%2);try{Thread.sleep(400L);}catch(Exception f){}}}

Sin golf:

static void k(double b,final int c,final int d){
        final int[][]a=new int[c+1][d+1];
        int i=0,j;
        for(;i<c;i++) {
            for(j=0;j<d;j++) {
                a[i][j]=Math.random()<b?Math.random()<0.5?1:2:0;
            }
        }

        Frame e=new Frame(){
            public void paint(Graphics g){
                setVisible(1>0);
                int i=0,j;
                for(;i<c;i++) {
                    for(j=0;j<d;j++) {
                        g.setColor(a[i][j]==2?Color.BLUE:a[i][j]==1?Color.RED:Color.WHITE);
                        g.drawLine(i,j,i,j);
                    }
                }
                for(i=c-1;i>=0;i--) {
                    for(j=d-1;j>=0;j--) {
                        if(a[i][j]==1&&a[i][(j+1)%d]==0){
                            a[i][(j+1)%d]=1;a[i][j]=0;
                        }else if(a[i][j]>1&&a[(i+1)%c][j]==0){
                            a[(i+1)%c][j]=2;a[i][j]=0;
                        }
                    }
                }
            }
        };
        e.show();
        while(1>0){e.setSize(c,d+i++%2);try{Thread.sleep(400L);}catch(Exception f){}}
    }

Imagen:

ingrese la descripción de la imagen aquí

Urna de pulpo mágico
fuente
No estoy familiarizado con Java, pero ¿son los nombres más cortos para colores rojo, azul y blanco? (tal vez el gris es una opción, ahorrando un byte vs blanco)
JAD
La captura de pantalla parece mostrar el mismo problema que el que describí aquí codegolf.stackexchange.com/questions/104742/a-2d-traffic-jam/…
qwr