2D пробка


17

Модель трафика Бихам-Миддлтон-Левин - это самоорганизующийся сотовый автомат, который моделирует упрощенный трафик.

Он состоит из нескольких автомобилей, представленных точками на решетке со случайной стартовой позицией, где каждый автомобиль может быть одного из двух типов: те, которые движутся только вниз (показано синим цветом в этой статье), и те, которые движутся только к правильно (показано красным цветом в этой статье). Два типа автомобилей по очереди двигаются. В течение каждого поворота все автомобили соответствующего типа продвигаются на один шаг, если они не заблокированы другим автомобилем.

Ваша задача визуализировать эту модель как анимацию. Вот несколько хороших демонстраций.

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

вход

Число с плавающей точкой от 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()}}

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

Функция, которая принимает 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

Mathematica, 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 x что-то) в 1-D List(длина = ширина * высота). Pad, 1если не хватает значений.

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


Да, использование встроенного больше, чем не использовать ?!
Адам

3

Dyalog APL , 190 108 115 112 байтов

Решение

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

TryAPL online (слегка измененный из-за сетевых ограничений):

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

  2. Сделай один шаг вниз.

  3. Сделайте один шаг вправо.

  4. Переходите к шагу 2.

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

объяснение

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

÷4 обратная 4 (0,25)

⎕DL подождите столько секунд (возвращает фактическое истекшее время)

⍵⊣ отбросить это в пользу ⍵ (правильный аргумент; сетка)

⎕← вывод, что

 транспонирования

⍉⍣⍺ транспонировать обратно снова, если ⍺ (левый аргумент; 0 = вниз, 1 = вправо)

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

  ,⍨ аргумент приложил к себе

  , добавлен в

   сам

)

 разбить матрицу на список списков

( поиск по регулярному выражению (объясняется здесь слева направо):

  ⍺⊃ выберите один из следующих двух на основе ⍺ (0 = вниз / первый, 1 = вправо / второй)

  '(↓+) ' '(→+) ' последовательности стрелок вниз и влево, сопровождаемые пробелом

)⎕R' \1' заменить на пробел, за которым следует найденная последовательность

 смешать список списков в матрицу

 транспонирования

d[⍺]↓ пропустите строки "height", если ⍺ (левый аргумент) равен 0 (вниз), или строк "width", если ⍺ равен 1 (справа)

d[⍺]↑ затем взять столько строк

 пройти через (служит разделителем)

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

}


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

 числовой ввод (размеры)

d← назначьте это на d

×/ умножить размеры (находит количество ячеек)

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, за исключением округления.


Ваше первоначальное поколение плат не гарантирует плату с плотностью ввода. Я предполагаю, что это выбор OP, позволять ли это или нет.
JungHwan Мин

О, @JarkoDubbeldam уже спросил об этом.
JungHwan Мин

@JungHwanMin Как так? Пусть плотность будет d. Каждая позиция получает значение между 0 и 1. Если между 0 и ᵈ/₂ становится ,. Если между ᵈ⁄₂ и d он становится . Если между d и 1 он остается пустым.
Адам

Что ж, крайний случай был бы: каждая позиция каким-то образом получает значение 0(потому что они (псевдо) - случайно генерируемые (псевдо) - независимо; очень маловероятно, но возможно). Тогда ваша доска полна с.
Юнг Хван Мин

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

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

Картина:

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


Не знакомы с Java, но красные, синие и белые - самые короткие названия цветов, которые вы можете использовать? (возможно, серый - вариант, сохраняя один байт против белого)
JAD

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