Un ingorgo 2D


17

Il modello di traffico Biham-Middleton-Levine è un automa cellulare auto-organizzante che modella il traffico semplificato.

Consiste in un numero di auto rappresentate da punti su un reticolo con una posizione di partenza casuale, in cui ogni auto può essere di due tipi: quelli che si muovono solo verso il basso (mostrati in blu in questo articolo) e quelli che si muovono solo verso il a destra (mostrato in rosso in questo articolo). I due tipi di auto si alternano per muoversi. Durante ogni curva, tutte le auto del tipo corrispondente avanzano di un passo se non sono bloccate da un'altra macchina.

Il tuo compito è visualizzare questo modello come un'animazione. Ecco alcune buone dimostrazioni.

inserisci qui la descrizione dell'immagine

Ingresso

Un numero in virgola mobile compreso tra 0 e 1 che rappresenta la densità e due numeri interi che rappresentano l'altezza e la larghezza della griglia visualizzate. Supponiamo che gli input siano validi e che i parametri di una funzione o della lettura dall'input dell'utente siano entrambi corretti.

Esempio: 0.38 144 89(corrisponde all'immagine sopra)

Produzione

Una griglia, almeno 80x80, che visualizza l'animazione di questo modello in esecuzione. All'inizio, le auto vengono posizionate casualmente sulla griglia fino a quando la griglia non raggiunge la densità di input, con metà rossa e metà blu (ovvero la densità per il numero totale di quadrati della griglia, arrotondati come preferisci). La densità deve essere questo valore, il che significa che non è possibile riempire ogni cella con densità come probabilità. Per ogni passaggio, un tipo di auto si sposta verso il basso o verso destra, avvolgendosi se oltrepassano il bordo. Il tipo di auto che si muove alterna ogni passaggio. Per rendere visibile l'animazione, devono essere presenti almeno 10 ms tra ogni passaggio.

Regole

  • Le auto possono avere qualsiasi colore o simbolo purché siano distinguibili tra loro e lo sfondo e ogni tipo di auto ha lo stesso colore o simbolo.

  • Consolle e output grafico sono entrambi consentiti. Per l'output della console, qualsiasi simbolo stampabile va bene, ma l'output deve essere una griglia di caratteri.

  • Per favore specifica quale tipo di output hai prodotto se non hai uno screenshot o una gif.

  • La simulazione deve essere eseguita per sempre.

L'output è un po 'complesso, quindi se avete domande, si prega di commentare.


Qualche limitazione su quanto lentamente o velocemente deve essere eseguita l'animazione?
xnor

Forse vale la pena specificare che il tipo di auto che si muove si alterna ad ogni passo.
Greg Martin,

@xnor Stavo pensando almeno 5 o 10 ms per loop, ma non sono davvero sicuro che sarebbe difficile misurarlo.
qwr

3
La densità significa che la densità deve essere quel valore o semplicemente che ogni pixel ha una probabilità d da riempire? Inoltre, dobbiamo assegnare il colore delle auto in modo casuale o no? Se a caso, è di nuovo ok se hanno solo una probabilità del 50-50 di essere di entrambi i colori?
JAD,

1
@JarkoDubbeldam La densità deve essere quel valore. Hanno una probabilità del 50-50 di essere di ogni colore. Tuttavia, ho risposto in ritardo, quindi le risposte potrebbero essere diverse. Le auto possono spostarsi verso l'alto o a sinistra.
qwr,

Risposte:


5

R, 350 338 293 291 273 268 264 byte

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()}}

Ungolfed:

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()
  }
}

Funzione che accetta 3 argomenti: dcome densità e dimensioni x,y. qè il numero di auto in ciascun colore. mè la matrice con le automobili, che inizialmente viene riempita prendendo una sorta casuale del numero di automobili e spazi vuoti. Le auto sono 1o -1, lo spazio vuoto è 0.

fè una funzione che sposta le macchine di una fila, guardando le macchine codificate come 1. Controlla se l'auto può muoversi controllando la presenza di 1s seguita da 0. Usiamo applycorrere fsu ogni riga o colonna, a seconda di quali auto.

f gestisce lo spostamento di 1 auto, per spostare le -1auto, trasponiamo la matrice, cambiando la direzione del movimento, moltiplicando la matrice per -1, così le -1auto diventano 1auto, e vv e la matrice risultante viene nuovamente trasformata.

Questo utilizza imageper creare la trama, usando 3 colori predefiniti per i tre valori. Utilizza il animationpacchetto per gestire le animazioni utilizzando le opzioni predefinite, ovvero 1 fps.

0.38, 144, 89:

Link a GIF

0.2, 144, 89:

Link a GIF

0.53, 144, 89:

Link a GIF


La tua animazione sembra davvero fantastica - che densità hai usato? Sembra che l'intera faccenda si sia inceppata abbastanza rapidamente con un sacco di spazio vuoto
qwr

@qwr che in realtà era qualcosa che mi dava fastidio. Nel mio programma il tutto si blocca a densità inferiori rispetto all'esempio che hai collegato. Non ricordo però i parametri esatti usati per la trama, ma potrebbe benissimo essere 0.38 144 89l'esempio.
JAD,

Giocando con le griglie quadrate ho ottenuto una densità di 0,35 per inceppare jasondavies.com/bml/#0.35/100/100 ma è quasi sempre una linea spessa di 45 gradi invece di sottili linee diagonali. Dato che le tue linee sembrano più verticali, penso che qualcosa con i due tipi di auto sia spento
qwr

Vedo il problema ora. Cara può avanzare solo se non è bloccata da un'altra macchina. Quindi negli esempi di Wikipedia tutte le auto in movimento hanno uno spazio davanti a loro. Ma nella tua animazione le macchine si muovono come una linea. Interessante.
qwr

Ah, lo farebbe.
JAD,

5

Matematica, 237 228 203 198 181 byte

(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]])&

L'output è dinamico Image. Lo sfondo è verde chiaro e le auto sono nere o magenta, a seconda della loro direzione.

Spiegazione

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

Crea la scheda iniziale:

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

Impostato i su 2. Crea un Listdi {0, 2}, la cui lunghezza è piano (densità * larghezza * altezza / 2) (diviso per due perché {0, 2}è lunghezza-2).

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

Rimodella la risultante 2-D List(2 x qualcosa) in 1-D List(lunghezza = larghezza * altezza). Riempi 1se non ci sono abbastanza valori.

RandomSample@ ...

(Pseudo-) ordina casualmente il risultato.

... ~Partition~#2

Partizione che risulta in lunghezza (larghezza).

b= ...

Conservalo in b .


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

Crea un Dynamic Image:

i=-i;

Capovolgi il segno di i .

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

Applicare l'automa cellulare con regole 193973693e con il prossimo pesi {{0, 0, 0}, {3, 9, 1}, {0, 0, 0}}ab trasporre. Impostare buguale a quello.

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

Se iè positivo, lascia in bpace. In caso contrario, trasporre il b( 2-è lì perché ho giocato a golf ilCellularAutomaton un po '). In sostanza, questo traspone bogni altra iterazione (per annullare la trasposizione)

Colorize[ ... ]

Converti l'array in un colorato Image .

Dynamic@ ...

Crea l'espressione Dynamic . cioè le funzioni sopra sono eseguite ripetutamente.

Produzione

Ecco un esempio di output (input: 0.35, 192, 108 per 2000 frame (ingrandito 2x).

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


Eh, usare il built-in è più lungo del non usarlo ?!
Adám,

3

Dyalog APL , 190 108 115 112 byte

Soluzione

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

TryAPL online (leggermente modificato a causa delle restrizioni online):

  1. Insieme ⎕IO←0, definiscono la funzione S , e quindi definire e visualizzare un casuale 38% 14 × 29 griglia, G .

  2. Fai uno spostamento verso il basso.

  3. Fai una mossa a destra.

  4. Vai al passaggio 2.

    Traffico
    Animazione dell'algoritmo precedente, che non garantiva la densità.

Spiegazione

S←{definire la funzione diretta S (spiegata qui da destra a sinistra):

÷4 reciproco di 4 (0,25)

⎕DL attendere molti secondi (restituisce il tempo trascorso effettivo)

⍵⊣ scartalo a favore di ⍵ (l'argomento giusto; la griglia)

⎕← uscita che

 trasporre

⍉⍣⍺ trasporre nuovamente se ⍺ (argomento sinistro; 0 = giù, 1 = destra)

( applica il treno di funzioni (spiegato qui da sinistra a destra):

  ,⍨ l'argomento si aggiunse a se stesso

  , aggiunto a

   si

)

 dividere la matrice in un elenco di elenchi

( cerca regex (spiegato qui da sinistra a destra):

  ⍺⊃ scegli una delle due seguenti in base a ⍺ (0 = giù / primo, 1 = destra / secondo)

  '(↓+) ' '(→+) ' sequenze di frecce giù e sinistra seguite da uno spazio

)⎕R' \1' sostituire con uno spazio seguito dalla sequenza trovata

 mescolare l'elenco di liste in matrice

 trasporre

d[⍺]↓ elimina le righe "height" se ⍺ (argomento a sinistra) è 0 (down) o le righe "width" se ⍺ è 1 (right)

d[⍺]↑ quindi prendi tante righe

 pass through (funge da separatore)

⍉⍣⍺ trasporre se ⍺ (argomento sinistro; 0 = giù, 1 = destra)

}


' ↓→'[ indicizza la stringa con (spiegato qui da destra a sinistra):

 input numerico (dimensioni)

d← assegnalo a d

×/ moltiplica le dimensioni (trova il conteggio delle celle)

c← assegnalo a c

⎕× moltiplicalo con l'input numerico (la densità)

 arrotondare per difetto

1 2⍴⍨ ripetere ciclicamente uno e due fino a quella lunghezza

c↑ estendilo fino alla lunghezza c , imbottitura con zeri

d⍴ usa d (le dimensioni) per rimodellare

{ applica questa funzione anonima a quella (spiegata qui da sinistra a destra):

  ⍵[ l'argomento giusto (l'elenco di zeri, uno e due) indicizzato da

   ?⍨ gli indici mescolati fino a

   ⍴⍵ la lunghezza dell'argomento

  ]

}

]

{ applica la seguente funzione anonima (spiegata da destra a sinistra):

0S⍵ applicare S con 0 (giù) come argomento a sinistra e la griglia come argomento a destra

1S con quello come argomento a destra, applica S con 1 (a destra) come argomento a sinistra

}⍣≡ fino a quando due iterazioni successive sono identiche (un ingorgo)

Appunti

  1. Richiede ⎕IO←0, che è predefinito su molti sistemi.

  2. Richiede (altezza, larghezza), quindi densità.

  3. Non utilizza alcun automa incorporato.

  4. Utilizza il supporto regex integrato.

  5. Si interrompe in caso di ingorgo (nessuna macchina può muoversi).

  6. Emette matrici di caratteri in cui rappresenta le macchine che si muovono a destra, rappresenta le macchine che si muovono verso il basso e gli spazi sono strade vuote.

  7. Come sopra, esce alla sessione a 4 Hz, ma la frequenza può essere regolata cambiando ÷4; ad es. ÷3è 3 Hz ed .3è ³⁄₁₀ Hz.

  8. È più facile vedere cosa sta succedendo se si esegue ]Box on -s=max -f=onprima.

  9. La distribuzione richiesta è ora garantita e i due tipi di auto si verificano esattamente tra 50 e 50, ad eccezione degli arrotondamenti.


La generazione della scheda iniziale non garantisce una scheda con la densità di input. Immagino sia la scelta di OP se permetterlo o no.
JungHwan Min,

Oh, @JarkoDubbeldam lo ha già chiesto.
JungHwan Min

@JungHwanMin In che modo? Lascia che la densità sia d. Ogni posizione ottiene un valore compreso tra 0 e 1. Se tra 0 e ᵈ/₂ diventa un ,. Se tra ᵈ⁄₂ e d diventa a . Se tra d e 1 rimane vuoto.
Adám,

Bene, un caso estremo sarebbe: ogni posizione in qualche modo ottiene il valore 0(perché sono (pseudo) - generati casualmente (pseudo) - indipendentemente; molto improbabili ma possibili). Quindi la tua tavola è piena di s.
JungHwan Min

@JungHwanMin Ah, capisco cosa intendi.
Adám,

1

Java (624 byte + 18 byte per Java.awt. * = 642 byte)

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){}}}

Ungolfed:

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){}}
    }

Immagine:

inserisci qui la descrizione dell'immagine


Non hai familiarità con Java, ma rosso, blu e bianco sono i nomi più brevi per i colori che puoi usare? (forse il grigio è un'opzione, salvando un byte contro il bianco)
JAD il

Lo screenshot sembra mostrare lo stesso problema di quello che ho descritto qui codegolf.stackexchange.com/questions/104742/a-2d-traffic-jam/…
qwr
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.