Ein 2D-Stau

17

Das Verkehrsmodell von Biham-Middleton-Levine ist ein selbstorganisierender Zellularautomat, der den vereinfachten Verkehr modelliert.

Es besteht aus einer Anzahl von Autos, die durch Punkte auf einem Gitter mit einer zufälligen Startposition dargestellt werden, wobei jedes Auto einer von zwei Typen sein kann: diejenigen, die sich nur nach unten bewegen (in diesem Artikel als blau dargestellt), und diejenigen, die sich nur in Richtung bewegen rechts (in diesem Artikel rot dargestellt). Die beiden Wagentypen bewegen sich abwechselnd. In jeder Runde rücken alle Autos des entsprechenden Typs um einen Schritt vor, wenn sie nicht von einem anderen Auto geblockt werden.

Ihre Aufgabe ist es, dieses Modell als Animation zu visualisieren. Hier sind einige gute Demonstrationen.

Bildbeschreibung hier eingeben

Eingang

Eine Gleitkommazahl zwischen 0 und 1 für die Dichte und zwei Ganzzahlen für die Höhe und Breite des angezeigten Rasters. Angenommen, Eingaben sind gültig, und Parameter für eine Funktion oder das Lesen von Benutzereingaben sind in Ordnung.

Beispiel: 0.38 144 89(entspricht obigem Bild)

Ausgabe

Ein Raster von mindestens 80 x 80, in dem die Animation dieses Modells angezeigt wird. Zu Beginn werden Autos nach dem Zufallsprinzip in das Raster eingefügt, bis das Raster die Eingabedichte mit der Hälfte Rot und der Hälfte Blau erreicht (dh Dichte multipliziert mit der Gesamtzahl der Rasterquadrate, gerundet, wie Sie möchten). Die Dichte muss dieser Wert sein, was bedeutet, dass Sie nicht jede Zelle mit einer Dichte als Wahrscheinlichkeit füllen können. Für jeden Schritt bewegt sich ein Wagentyp entweder nach unten oder nach rechts und umgibt ihn, wenn er die Kante passiert. Die Art des sich bewegenden Autos wechselt bei jedem Schritt. Um die Animation sichtbar zu machen, müssen zwischen jedem Schritt mindestens 10 ms liegen.

Regeln

  • Die Fahrzeuge können eine beliebige Farbe oder ein beliebiges Symbol haben, sofern sie voneinander und vom Hintergrund unterscheidbar sind und jeder Fahrzeugtyp dieselbe Farbe oder dasselbe Symbol aufweist.

  • Konsolen- und Grafikausgabe sind zulässig. Für die Konsolenausgabe ist jedes druckbare Symbol in Ordnung, die Ausgabe muss jedoch als Zeichenraster erfolgen.

  • Bitte geben Sie an, welche Art von Ausgabe Sie erstellt haben, wenn Sie keinen Screenshot oder kein GIF haben.

  • Die Simulation muss für immer laufen.

Die Ausgabe ist etwas komplex. Wenn Sie Fragen haben, kommentieren Sie diese bitte.

qwr
quelle
Gibt es Einschränkungen, wie langsam oder schnell die Animation ausgeführt werden muss?
Xnor
Vielleicht lohnt es sich anzugeben, dass die Art des Autos, das sich bewegt, sich bei jedem Schritt abwechselt.
Greg Martin
@xnor Ich dachte an mindestens 5 oder 10 ms pro Schleife, bin mir aber nicht sicher, ob das schwer zu messen ist.
Qwr
3
Bedeutet die Dichte , dass die Dichte hat dieser Wert sein, oder einfach nur , dass jedes Pixel eine Wahrscheinlichkeit d gefüllt werden muss? Müssen wir auch die Farbe der Autos zufällig zuweisen oder nicht? Wenn zufällig, ist es wieder in Ordnung, wenn sie nur eine 50-50 Chance haben, eine der beiden Farben zu sein?
JAD
1
@ JarkoDubbeldam Die Dichte muss dieser Wert sein. Sie haben eine 50-50 Chance, jede Farbe zu haben. Ich habe jedoch zu spät geantwortet, daher können die Antworten unterschiedlich sein. Autos können nach oben oder links fahren.
Qwr

Antworten:

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

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

Funktion, die 3 Argumente akzeptiert: dals Dichte und Dimensionen x,y. qist die Anzahl der Autos in jeder Farbe. mist die Matrix mit Autos, die anfänglich gefüllt wird, indem eine zufällige Art der Anzahl von Autos und leeren Räumen genommen wird. Autos sind entweder1 oder -1, Leerraum ist 0.

fist eine Funktion, die die Autos um eine Reihe bewegt und die Autos mit der Codierung 1. Es prüft, ob sich das Auto bewegen kann, indem es auf 1s überprüft, gefolgt von0 . Wir applyrennen fin jeder Reihe oder Spalte, je nachdem welches Auto.

fkümmert sich um die Bewegung der 1Autos, um die zu bewegen-1 Autos , transponieren wir die Matrix, ändern die Bewegungsrichtung, multiplizieren die Matrix mit -1, so dass die -1Autos zu 1Autos werden, und vv und die resultierende Matrix werden erneut transformiert.

Hiermit wird imagedas Diagramm erstellt, wobei drei Standardfarben für die drei Werte verwendet werden. Verwendet das animationPaket, um die Animationen mit den Standardoptionen (1 fps) zu verarbeiten.

0.38, 144, 89:

Link zu GIF

0.2, 144, 89:

Link zu GIF

0.53, 144, 89:

Link zu GIF

JAD
quelle
Ihre Animation sieht wirklich cool aus - welche Dichte haben Sie verwendet? Scheint, als ob das Ganze ziemlich schnell mit viel
freiem
@qwr das war eigentlich etwas was mich störte. In meinem Programm staut sich das Ganze bei geringeren Dichten als in dem von Ihnen verlinkten Beispiel. Ich kann mich zwar nicht an die genauen Parameter erinnern, die für den Plot verwendet wurden, aber es könnte sehr gut die 0.38 144 89aus dem Beispiel sein.
JAD
Wenn ich mit quadratischen Gittern herumspiele , habe ich eine Dichte von 0,35, um jasondavies.com/bml/#0.35/100/100 zu stören, aber es ist fast immer eine dicke 45-Grad-Linie anstelle dünner diagonaler Linien. Da deine Linien vertikaler aussehen, denke ich, dass etwas mit den beiden
Autotypen nicht stimmt
Ich sehe das Problem jetzt. Cara kann nur vorrücken, wenn sie nicht von einem anderen Auto geblockt werden. In den Wikipedia-Beispielen haben alle sich bewegenden Autos ein Leerzeichen vor sich. Aber in Ihrer Animation bewegen sich die Autos als Linie. Interessant.
Qwr
Ah, das würde es tun.
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]])&

Die Ausgabe ist dynamisch Image . Der Hintergrund ist hellgrün und die Autos sind je nach Fahrtrichtung schwarz oder magenta.

Erläuterung

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

Erstelle das erste Board:

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

Stellen Sie iauf 2. Erstellen Sie ein Listvon {0, 2}, dessen Länge der Boden ist (Dichte * Breite * Höhe / 2) (geteilt durch zwei, weil {0, 2}Länge-2 ist).

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

Formen Sie die resultierende 2D List(2 x etwas) in 1-D List(Länge = Breite * Höhe). Pad, 1wenn nicht genügend Werte vorhanden sind.

RandomSample@ ...

Sortieren Sie das Ergebnis (pseudo-) zufällig.

... ~Partition~#2

Partition, die in Länge (Breite) resultiert.

b= ...

Bewahren Sie das 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]]

Erstellen Sie ein Dynamic Image:

i=-i;

Kippen Sie das Zeichen von i.

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

Wenden Sie den Zellularautomaten mit Regel- 193973693und Nachbargewichten {{0, 0, 0}, {3, 9, 1}, {0, 0, 0}}auf btransponiert an. Setze das bgleich.

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

Wenn ies positiv ist, lassen Sie es in bRuhe. Wenn nicht, transponiere das b( 2-ist da, weil ich das CellularAutomatonein bisschen golfen habe ). Dies transponiert bim Wesentlichen jede zweite Iteration (um die Transposition rückgängig zu machen).

Colorize[ ... ]

Wandle das Array in ein buntes um Image.

Dynamic@ ...

Mache den Ausdruck Dynamic. dh die obigen Funktionen werden wiederholt ausgeführt.

Ausgabe

Hier ist eine Beispielausgabe (Eingaben:) 0.35, 192, 108für 2000 Bilder (2x vergrößert).

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

JungHwan min
quelle
Huh, das eingebaute zu benutzen ist länger als es nicht zu benutzen ?!
Adám
3

Dyalog APL , 190 108 115 112 Bytes

Lösung

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

TryAPL online (geringfügig geändert aufgrund von Online-Einschränkungen):

  1. Setze ⎕IO←0, definiere die Funktion S und definiere und zeige dann ein zufälliges 38% 14 × 29-Gitter G an .

  2. Mach eine Bewegung nach unten.

  3. Machen Sie eine Bewegung nach rechts.

  4. Weiter zu Schritt 2.

    Der Verkehr
    Animation des vorherigen Algorithmus, der die Dichte nicht garantierte.

Erläuterung

S←{Definieren Sie die direkte Funktion S (hier von rechts nach links erklärt):

÷4 Kehrwert von 4 (0,25)

⎕DL warte so viele Sekunden (gibt die tatsächlich verstrichene Zeit zurück)

⍵⊣ verwerfe das zugunsten von ⍵ (das richtige Argument; das Gitter)

⎕← gib das aus

 transponieren

⍉⍣⍺ transponiere wieder zurück wenn if (das linke Argument; 0 = runter, 1 = rechts)

( wende den Funktionszug an (hier von links nach rechts erklärt):

  ,⍨ das Argument hing an sich

  , angehängt an

   selbst

)

 Matrix in Liste von Listen aufteilen

( Suche nach Regex (hier von links nach rechts erklärt):

  ⍺⊃ wähle eine der folgenden zwei basierend auf ⍺ (0 = unten / zuerst, 1 = rechts / Sekunde)

  '(↓+) ' '(→+) ' Abwärts- und Linkspfeil, gefolgt von einem Leerzeichen

)⎕R' \1' Ersetzen Sie durch ein Leerzeichen, gefolgt von der gefundenen Sequenz

 Liste der Listen in Matrix mischen

 transponieren

d[⍺]↓ "height" -Zeilen löschen, wenn ⍺ (linkes Argument) 0 (nach unten) ist, oder "width" -Zeilen löschen, wenn ⍺ 1 (rechts) ist

d[⍺]↑ Nehmen Sie dann so viele Zeilen

 passieren (dient als Trennzeichen)

⍉⍣⍺ transponiere wenn ⍺ (das linke Argument; 0 = unten, 1 = rechts)

}


' ↓→'[ indexiere den String mit (hier von rechts nach links erklärt):

 numerische Eingabe (Maße)

d← ordne das d zu

×/ multiplizieren Sie die Dimensionen (findet die Anzahl der Zellen)

c← weise das zu c

⎕× multiplizieren Sie das mit numerischer Eingabe (die Dichte)

 abrunden

1 2⍴⍨ Wiederholen Sie zyklisch eins und zwei bis zu dieser Länge

c↑ verlängern Sie das, bis Länge c , Auffüllen mit Nullen

d⍴ Verwenden Sie d (die Abmessungen), um die Form zu ändern

{ wende diese anonyme Funktion darauf an (hier von links nach rechts erklärt):

  ⍵[ das richtige Argument (die Liste der Nullen, Einsen und Zweien), indiziert durch

   ?⍨ die gemischten Indizes bis zu

   ⍴⍵ die Länge des Arguments

  ]

}

]

{ wende die folgende anonyme Funktion an (von rechts nach links erklärt):

0S⍵ wende S mit 0 (nach unten) als linkes Argument und das Gitter als rechtes Argument an

1S Wenden Sie mit diesem als rechtes Argument S mit 1 (rechts) als linkes Argument an

}⍣≡ bis zwei aufeinanderfolgende Iterationen identisch sind (ein Stau)

Anmerkungen

  1. Benötigt ⎕IO←0, was bei vielen Systemen Standard ist.

  2. Fordert zur Eingabe von (Höhe, Breite) und dann zur Eingabe der Dichte auf.

  3. Verwendet keinen eingebauten Automaten.

  4. Verwendet die integrierte Regex-Unterstützung.

  5. Stoppt bei Stau (kein Auto kann sich bewegen).

  6. Gibt Zeichenmatrizen aus, in denen sich Autos nach rechts bewegen, sich nach unten bewegen und Leerzeichen leere Straßen sind.

  7. Wie oben erfolgt die Ausgabe an die Sitzung mit 4 Hz, die Frequenz kann jedoch durch Ändern angepasst werden ÷4. zB ÷3ist 3 Hz und .3ist ³⁄₁⁄ Hz.

  8. Es ist einfacher zu sehen, was passiert, wenn ]Box on -s=max -f=onzuerst ausgeführt wird.

  9. Die erforderliche Aufteilung ist nun gewährleistet, und die beiden Wagentypen kommen bis auf die Rundung genau zu 50% vor.

Adam
quelle
Ihre erste Kartengeneration garantiert keine Karte mit der Eingabedichte. Ich denke, es liegt an OP, ob er das zulässt oder nicht.
JungHwan Min
Oh, @JarkoDubbeldam hat das schon gefragt.
JungHwan Min
@JungHwanMin Wie so? Die Dichte sei d. Jede Position wird einen Wert zwischen 0 und 1. Wenn zwischen 0 und ᵈ/₂ wird es ein . Wenn zwischen ᵈ⁄₂ und d, wird es a . Wenn zwischen d und 1, bleibt es leer.
Adám
Nun, ein Extremfall wäre: Jede Position bekommt irgendwie den Wert 0(weil sie (pseudo-) zufällig (pseudo-) unabhängig erzeugt werden; sehr unwahrscheinlich, aber möglich). Dann ist dein Board voll mit s.
JungHwan Min
@JungHwanMin Ah, ich verstehe, was du meinst.
Adám
1

Java (624 Bytes + 18 Bytes für 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){}}}

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

Bild:

Bildbeschreibung hier eingeben

Magische Kraken-Urne
quelle
Sie kennen Java nicht, aber sind Rot, Blau und Weiß die kürzesten Namen für Farben, die Sie verwenden können? (Vielleicht ist Grau eine Option, um ein Byte gegen Weiß zu sparen)
JAD
Der Screenshot erscheint das gleiche Problem wie zu zeigen , was ich hier beschrieben codegolf.stackexchange.com/questions/104742/a-2d-traffic-jam/...
QWR