2D пробка


17

Модель руху Biham-Middleton-Levine - це самоорганізується стільниковий автомат, який моделює спрощений рух.

Він складається з декількох автомобілів, представлених точками на решітці з випадковим початковим положенням, де кожен автомобіль може бути одного з двох типів: автомобілів, які рухаються лише вниз (показані синьою в цій статті), і тих, які рухаються лише у напрямку до праворуч (у цій статті зображено червоним кольором). Автомобілі двох типів по черзі рухаються. Під час кожного ходу всі автомобілі відповідного типу просуваються на один крок, якщо їх не блокує інший автомобіль.

Ваше завдання - візуалізувати цю модель як анімацію. Ось кілька хороших демонстрацій.

введіть тут опис зображення

Вхідні дані

Число з плаваючою комою між 0 і 1, що представляє щільність, і два цілі числа, що представляють відображену висоту і ширину сітки. Припустимо, що введення є дійсними, а параметри функції або зчитування з введення користувача є нормальними.

Приклад: 0.38 144 89(відповідає зображенню вище)

Вихідні дані

Сітка, принаймні 80x80, яка відображає анімацію цієї моделі, що працює. На початку автомобілі випадковим чином розміщуються на сітці до тих пір, поки сітка не досягне вхідної щільності, з половиною червоного та наполовину синього (тобто в рази щільність загальна кількість квадратів сітки, округлена як би вам не подобалося). Щільність повинна бути цією величиною, це означає, що ви не можете заповнити кожну клітинку щільністю як імовірність. На кожному кроці один тип автомобіля або рухається вниз, або вправо, загортаючись, якщо вони йдуть повз край. Тип автомобіля, що рухається, чергує кожен крок. Щоб зробити анімацію видимою, між кожним кроком повинно бути не менше 10 мс.

Правила

  • Автомобілі можуть бути будь-яких кольорів або символів, якщо вони відрізняються один від одного і від фону, і кожен тип автомобіля є одного кольору або символу.

  • Консольний та графічний вихід дозволені. Для виводу з консолі будь-який символ для друку добре, але вихід має бути сіткою символів.

  • Вкажіть, будь ласка, який тип продукту ви створили, якщо у вас немає скріншоту або gif.

  • Моделювання має працювати вічно.

Вихід є трохи складним, тому якщо у вас є якісь питання, будь ласка, прокоментуйте.


Будь-які обмеження щодо того, наскільки повільно чи швидко мусить працювати анімація?
xnor

Можливо, варто уточнити, що тип автомобіля, який рухається, чергується на кожен крок.
Грег Мартін

@xnor Я думав щонайменше 5 або 10 мс на цикл, але я не дуже впевнений, чи важко це виміряти.
qwr

3
Чи означає щільність , що щільність має бути цим значенням, або просто , що кожен піксель має ймовірність д бути заповнена? Також, чи маємо ми призначати колір автомобілів випадковим чином чи ні? Якщо випадково, знову ж це нормально, якщо вони просто мають 50-50 шансів бути будь-якого кольору?
JAD

1
@JarkoDubbeldam Щільність повинна бути такою величиною. Вони мають 50-50 шансів бути кожного кольору. Однак я відповів пізно, тому відповіді можуть бути різними. Автомобілі можуть рухатися вгору або вліво.
qwr

Відповіді:


5

R, 350 338 293 291 273 268 264 байт

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

Безумовно:

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

Функція , яка приймає 3 аргументу: dяк щільність і розміри x,y. q- кількість автомобілів у кожному кольорі. m- це матриця з автомобілями, яку спочатку заповнюють, приймаючи випадкову кількість кількості машин та порожніх місць. Автомобілі є 1або -1, порожній простір є 0.

fце функція, яка рухає машини в один ряд, дивлячись на машини, кодовані як 1. Він перевіряє, чи може автомобіль рухатись, перевіряючи наявність 1s, а за ним 0. Ми використовуємо applyдля бігу fпо кожному рядку чи стовпцю, залежно від того, які машини.

fми обробляємо рух 1автомобілів, щоб рухати -1машини, ми переносимо матрицю, змінюючи напрямок руху, множимо матрицю на -1, так що -1машини стають1 машинами, а vv і отримана матриця знову перетворюється.

Це використовується imageдля створення сюжету, використовуючи 3 кольори за замовчуванням для трьох значень. Використовує animationпакет для обробки анімації, використовуючи параметри за замовчуванням, що становить 1 кадр в секунду.

0.38, 144, 89:

Посилання на GIF

0.2, 144, 89:

Посилання на GIF

0.53, 144, 89:

Посилання на GIF


Ваша анімація виглядає дуже класно - яку щільність ви використовували? Здається, що вся справа заклинила досить швидко з великою кількістю порожнього місця
qwr

@qwr, що насправді щось мене турбувало. У моїй програмі все заклинюється при меншій щільності, ніж у прикладі, який ви зв'язали. Я не можу пригадати точні параметри, які використовуються для сюжету, але це могло б бути 0.38 144 89з прикладу.
JAD

Граючи навколо квадратних сіток, я отримав щільність 0,35 для заклинювання jasondavies.com/bml/#0.35/100/100, але це майже завжди одна товста лінія 45 градусів замість тонких діагональних ліній. Оскільки ваші лінії виглядають більш вертикальними, я думаю, що щось із двома типами автомобілів вимкнено
qwr

Я зараз бачу проблему. Кара може просуватися лише в тому випадку, якщо їх не заблокує інша машина. Тож у прикладах Вікіпедії всі рухомі машини мають перед ними пробіл. Але у вашій анімації машини рухаються як лінія. Цікаво.
qwr

Ах, це зробить це.
JAD

5

Математика, 237 228 203 198 181 байт

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

Вихід є динамічним Image. Фон світло-зелений, а машини чорні або пурпурові, залежно від їх напрямку.

Пояснення

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

Створіть початкову дошку:

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

Набір iдля 2. Створити Listз {0, 2}, довжина якої підлогу (щільність * ширина * висота / 2) (ділиться на два , бо{0, 2} це довжина-2).

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

Переформатуйте отриманий 2-D List(2 х щось) на 1-D List(довжина = ширина * висота). Pad1 якщо не вистачає значень.

RandomSample@ ...

(Псевдо-) випадковим чином сортувати результат.

... ~Partition~#2

Розділ, що призводить до довжини (ширині).

b= ...

Зберігати це в b.


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

Створити Dynamic Image :

i=-i;

Переверніть знак i .

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

Застосовуйте стільниковий автомат із правилами 193973693та сусідськими вагами {{0, 0, 0}, {3, 9, 1}, {0, 0, 0}}до bпереміщених. Встановіть bрівне.

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

Якщо iпозитив, залиште в bспокої. Якщо ні, перенесіть b( 2-є, тому що я трохи пограв у гольф CellularAutomaton). По суті, це переносить bусі інші ітерації (щоб скасувати транспозицію)

Colorize[ ... ]

Перетворити масив у барвистий Image.

Dynamic@ ...

Складіть вираз Dynamic. тобто зазначені вище функції виконуються повторно.

Вихідні дані

Ось зразок виводу (входи:) 0.35, 192, 108для 2000 кадрів (збільшено в 2 рази).

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


Так, користуватися вбудованим довше, ніж не використовувати його ?!
Adám

3

Діялог APL , 190 108 115 112 байт

Рішення

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

TryAPL в Інтернеті (трохи змінено через обмеження в Інтернеті):

  1. Набір ⎕IO←0, визначить функцію S , а потім визначити і відобразити випадковий 38% 14 × 29 сітки, G .

  2. Зробіть один рух вниз.

  3. Зробіть один хід вправо.

  4. Перейдіть до кроку 2.

    Трафік
    Анімація попереднього алгоритму, який не гарантував щільності.

Пояснення

S←{визначити пряму функцію S (пояснюється тут справа наліво):

÷4 зворотний 4 (0,25)

⎕DL зачекайте стільки секунд (повертає фактично минулий час)

⍵⊣ відкиньте це на користь ⍵ (правильний аргумент; сітка)

⎕← висновок, що

 переносити

⍉⍣⍺ знову перемістити назад, якщо ⍺ (лівий аргумент; 0 = вниз, 1 = праворуч)

( застосувати функцію поїзда (пояснено тут зліва направо):

  ,⍨ аргумент додав до себе

  , додається до

   себе

)

 розділити матрицю на список списків

( регекс пошуку (пояснено тут зліва направо):

  ⍺⊃ виберіть одне з наступних двох на основі ⍺ (0 = вниз / перший, 1 = право / друге)

  '(↓+) ' '(→+) ' послідовності стрілок вниз та вліво з подальшим пробілом

)⎕R' \1' замініть пробіл з наступною знайденою послідовністю

 змішати список списків у матрицю

 переносити

d[⍺]↓ опустити рядки "висота", якщо ⍺ (лівий аргумент) 0 (вниз) або "ширина" рядків, якщо ⍺ дорівнює 1 (праворуч)

d[⍺]↑ тоді візьміть стільки рядів

 пройти через (служить роздільником)

⍉⍣⍺ перенести, якщо ⍺ (лівий аргумент; 0 = вниз, 1 = право)

}


' ↓→'[ індексуйте рядок за допомогою (пояснено тут справа наліво):

 числовий вхід (розміри)

d← призначити це d

×/ помножити розміри (кількість значень комірок)

c← призначити це c

⎕× помножити на числовий вхід (щільність)

 округлити вниз

1 2⍴⍨ циклічно повторюйте один і два до цієї довжини

c↑ продовжуйте це до довжини с , оббиваючи нулями

d⍴ використовувати d (розміри), щоб змінити форму

{ застосувати цю анонімну функцію до цього (пояснено тут зліва направо):

  ⍵[ правильний аргумент (список нулів, одиниць і подвійних), індексований

   ?⍨ перетасовані індекси до

   ⍴⍵ тривалість аргументу

  ]

}

]

{ застосувати таку анонімну функцію (пояснюється справа наліво):

0S⍵ застосувати S з 0 (вниз) як лівий аргумент, а сітку - як аргумент праворуч

1S при цьому в якості правого аргументу застосуйте S з 1 (правою) як лівий аргумент

}⍣≡ поки дві послідовні ітерації не збігаються (затор)

Примітки

  1. Вимагає ⎕IO←0, що для багатьох систем за замовчуванням.

  2. Підказки для (висота, ширина), а потім для щільності.

  3. Не використовує жодного вбудованого автомата.

  4. Використовується вбудована підтримка регулярних виразів.

  5. Зупиняється, якщо є пробки (жоден автомобіль не може рухатися).

  6. Виводить символьні матриці, де зображено машини, що рухаються праворуч, представляє автомобілі, що рухаються вниз, а пробіли - порожні дороги.

  7. Як зазначено вище, він виводить на сеанс 4 Гц, але частоту можна регулювати зміною ÷4; наприклад, ÷3становить 3 Гц і .3становить ³⁄₁₀ Гц.

  8. Легше зрозуміти, що відбувається, якщо виконати ]Box on -s=max -f=onспочатку.

  9. Необхідний розподіл зараз гарантований, і два типи автомобілів трапляються рівно в 50-50, крім економії.


Ваша початкова генерація плати не гарантує плату з щільністю введення. Я думаю, що це вибір вибору ОП, дозволити це чи ні.
JungHwan Min

О, @JarkoDubbeldam вже про це запитав.
JungHwan Min

@JungHwanMin Як це? Нехай щільність буде d. Кожна позиція отримує значення між 0 і 1. Якщо між 0 і ᵈ / ₂ стає ,. Якщо між ᵈ⁄₂ і d вона стає a . Якщо між d і 1 він залишається порожнім.
Адам

Ну, крайнім випадком буде: кожна позиція якось набуває значення 0(тому що вони (псевдо) -випадково генеруються (псевдо) -незалежно; дуже малоймовірно, але можливо). Тоді ваша дошка заповнена s.
JungHwan Min

@JungHwanMin Ах, я бачу, що ти маєш на увазі.
Адам

1

Java (624 байти + 18 байт для Java.awt. * = 642 байти)

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

Безумовно:

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

Картина:

введіть тут опис зображення


Не знайомий з java, але червоний, синій та білий найкоротші назви кольорів, які ви можете використовувати? (можливо, сірий - це варіант, економлячи один байт проти білого)
JAD,

Знімок екрана показує ту ж проблему, що і те, що я описав тут codegolf.stackexchange.com/questions/104742/a-2d-traffic-jam/…
qwr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.