Псевдослучайный сотовый автомат


14

Вступление

В этой задаче мы будем моделировать некоторый вероятностный клеточный автомат, используя очень плохие псевдослучайные числа. Клеточный автомат определяется на двоичных строках по следующему локальному правилу. Предположим, что левый сосед ячейки и сама ячейка имеют состояния aи b.

  • Если min(a,b) == 0, то новое состояние bIS max(a,b).
  • Если min(a,b) == 1, то новое состояние bвыбирается случайным образом из {0,1}.

Следующая картина показывает одну возможную 10-ступенчатую эволюцию сингла 1.

1
11
101
1111
11001
101011
1111111
10001001
110011011
1010111101

Обратите внимание, как два соседних 1s иногда эволюционируют 1, а иногда 0и биты 1с наибольшей границей всегда равны s. Ваша задача - создать клеточный автомат эволюции этой формы.

входные

Ваши входные данные представляют собой положительное целое число n, обозначающее количество отображаемых строк, и непустой список битов L, который мы используем в качестве источника случайности.

Выход

Ваш вывод представляет собой список списков или двумерный массив битов, изображающий эволюцию одного 1за nвременные шаги, как показано на рисунке выше. Вы можете дополнить вывод 0s, чтобы получить строки равной длины, если это необходимо, но не должно быть начальных 0s.

Случайные выборы в клеточном автомате должны быть взяты из списка L, возвращаясь к началу, когда он исчерпан. Более конкретно, если выходные данные пройдены по одной строке за время сверху вниз, слева направо, то последующие случайные выборы должны формировать список, Lповторяемый столько раз, сколько необходимо.

пример

Предположим, что входы n = 7и L = [0,1,0]. Затем клеточный автомат развивается следующим образом в течение 7 шагов, где мы ставим vправо выше любого случайного выбора:

[1]

[1,1]
   v
[1,0,1]

[1,1,1,1]
   v v v
[1,1,0,0,1]
   v
[1,1,1,0,1,1]
   v v   v
[1,0,0,1,1,1,1]

Если мы прочитаем все биты, помеченные знаком v, мы получим 01001001, что Lповторяется 2,66 раза. Следующий случайный бит будет 0.

Правила и оценки

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

Тестовые случаи

Детерминированная версия, каждый случайный бит 0:

Inputs: 10 [0]
Output:
1
11
101
1111
10001
110011
1010101
11111111
100000001
1100000011

Каждый случайный бит это 1:

Inputs: 6 [1,1]
Output:
1
11
111
1111
11111
111111

Псевдослучайные версии:

Inputs: 10 [0,0,1]
Output:
1
11
101
1111
10101
111111
1010011
11110101
101011111
1111101001

Inputs: 10 [1,0,0,1]
Output:
1
11
111
1001
11011
111111
1001101
11010111
111111101
1011001111

Inputs: 15 [1,1,1,0,0,0]
Output:
1
11
111
1111
10001
110011
1110111
11011001
111111011
1100011111
11100100011
111101100101
1001111101111
11011000111111
101101001011101

Ответы:


3

Pyth, 33 байта

jjLk.u++1m?hSde=.<Q1sd.:N2 1tvz]1

Попробуйте онлайн: демонстрация или тестовый набор

Объяснение:

jjLk.u++1m?hSde=.<Q1sd.:N2 1tvz]1  implicit: Q = input list
    .u                      tvz]1  reduce N=[1] input-1 times by applying
                      .:N2           all substrings of length 2
         m                           map each d of ^ to:
          ?hSd                         if min(d) = 0 then:
               =.<Q1                     rotate Q by one
              e                          and use the last element
                    sd                 else use sum(d) (=max(d))
      ++1                  1         add a 1 at the front and the back
                                   .u gives all intermediate results
 jLk                               join these lists to strings
j                                  print each string on a line

7

Сетчатка , 139 байт

^.
1

 00:0 01:1 10:1 11:
(m`^(..)((\S*)(?<=0) .*)
$1$3#$1!$2
+m`(?<=^(?<-2>.)*(..).*?#(.)*.)\d!(.)(.*\1:)(.)(\d*)
$5$3!$4$6$5
)`!0
0
 .+
<empty>

Где <empty>указывает, что есть конечная пустая строка. Каждая строка идет в отдельном файле и #должна быть заменена на перевод строки (0x0A).

Предполагается, что входные данные будут nв унарном формате (состоящем из нулей, как в Unary ), за которым следует пробел, за которым следует строка «псевдослучайный», например 10, [1, 0, 0, 1], будет читаться как

0000000000 1001

Вывод такой же, как в вызове, но дополнен нулями, например

1000000000
1100000000
1110000000
1001000000
1101100000
1111110000
1001101000
1101011100
1111111010
1011001111

Это было намного сложнее, чем я ожидал ...


3

Python, 142 135 132 131 байт

133 132 131 байтовая версия

f=input;n=f();L=f()*n*n;r=[1];i=1
while i<=n:print r;r=[L.pop(0)if r[x-1]&r[x]else r[x-1]+r[x]for x in range(1,i)];r=[1]+r+[1];i+=1

заменены r[x-1]+r[x]>1на r[x-1]&r[x]были оператор побитового & дает минимальное значение в(r[x-1],r[x])

Спасибо @ThomasKwa за предложение, n*nвместо n**2которого экономит 1 байт!

Спасибо @Shebang за -1 байт

135-байтовая версия

f=input;n=f();L=f()*n**2;r=[1];i=1
while i<=n:print r;r=[L.pop(0)if r[x-1]+r[x]>1 else r[x-1]+r[x]for x in range(1,i)];r=[1]+r+[1];i+=1

Спасибо @Cole за -7 байтов:

min(r[x-1],r[x])->r[x-1]+r[x]>1

max(r[x-1],r[x])->r[x-1]+r[x]

142-байтовая версия

f=input;n=f();L=f()*n**2;r=[1];i=1
while i<=n:print r;r=[L.pop(0)if min(r[x-1],r[x])else max(r[x-1],r[x])for x in range(1,i)];r=[1]+r+[1];i+=1

Даже близко не к ответу @ Jakube, но мне было очень интересно писать код и играть в гольф.

Ожидается два входа: первый вход - это число строк, а второй - список источников псевдослучайности . Он печатает на консоли один ряд за другим, каждый на новой строке.

В качестве примера:

10 # This is input
[0] # This is input
[1] <- First output row
[1, 1]
[1, 0, 1]
[1, 1, 1, 1]
[1, 0, 0, 0, 1]
[1, 1, 0, 0, 1, 1]
[1, 0, 1, 0, 1, 0, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 0, 0, 0, 0, 0, 0, 1, 1]

Теперь короткое объяснение того, как это работает:

f=input;n=f();L=f()*n*n;r=[1];i=1 First we define the input() function as f 
                                   for saving bytes as we have to call it twice.
                                   Then L is defined as a list made of the 
                                   pseudorandom numbers in their order *many* times 
                                   (were *many* is an upperbound of the canges that 
                                   could be done); r as the first row and i as the row 
                                   counter.

while i<=n:print r                 A while loop that exits when the nth row has been 
                                   calculated and the printing of the actual row.

r=[L.pop(0)if r[x-1]&r[x] else r[x-1]+r[x] for x in range(1,i)];r=[1]+r+[1];i+=1
     ^           ^                 ^                         ^
     |           |                 |Same as max(r[x-1],r[x]) | from 2nd to last element
     |           | Same as min(r[x-1],r[x]) (0->False;1->True)                
     | get random bit from pseudorandom list    

Хитрость в том, что мы знаем, что список битов всегда будет начинаться и заканчиваться на a, 1потому что первый и последний элементы никогда не изменяются из-за спецификаций. вопроса. Это причина для заявления [1]+r+[1].

Но если rинициализируется как [1], в первом ряду нет никаких изменений, а затем мы добавляем, [1]+r+[1]почему во втором ряду нет [1,1,1]?

Это связано с тем , что на первой итерации i=1так range(1,i)возвращает пустой список, и в результате forв списке понимание нечего перебирать rстановится пустой список так [1]+r+[1]=[1,1]. Это просто происходит на первой итерации, которая идеально подходит для нас!

PS: не стесняйтесь делать какие-либо предложения о том, как играть в гольф больше.


1
Приношу свои извинения, если я не правильно понимаю задачу, но вы не можете заменить min(a,b)на a+b>1и max(a,b)с a+b? Я понимаю, что вам, вероятно, придется что-то сделать, чтобы обработать самый первый случай 1-> 11(я думаю, вы могли бы сделать это L=[1]+f()...или найти какой-нибудь способ вставить 1 в начале, Lпотому что это всегда выдает 1 для второй строки)
Коул

@Cole К счастью, в остальную часть программы не нужно вносить никаких изменений, поскольку эти изменения влияют только на способ определения минимальных и максимальных значений пары битов.
Иоанн

1
Вы пропустили, что вы можете удалить пробел здесь: r[x-1]&r[x] else:)
Kade

Будет ли n ** 2 -> n * n работать?
lirtosiast

@ Томас Ты прав!
Иоанн

2

MATLAB, 146 143 138

(Также работает в Octave онлайн, но вам необходимо войти в систему, чтобы сохранить функцию в файле).

function o=c(n,L);o=zeros(n);o(:,1)=1;for i=2:n;for j=2:i;a=o(i-1,j-1);b=o(i-1,j);c=a|b;d=a&b;c(d)=L(d);L=circshift(L,-d);o(i,j)=c;end;end

Функция принимает входные данные nи Lи возвращает массив, oкоторый содержит выходные данные.

Для входных значений n- скаляр и Lвектор-столбец, который можно указывать в формате [;;;]. Не совсем то, что вы показываете, но вы говорите, что оно гибкое в разумных пределах, и это кажется так.

Вывод форматируется как n x nмассив, содержащий 0 и 1.

И объяснение:

function o=c(n,L)
%Create the initial array - an n x n square with the first column made of 1's
o=zeros(n);o(:,1)=1;
%For each row (starting with the second, as the first is done already)
for i=2:n;
    %For each column in that row, again starting with the second as the first is done
    for j=2:i;
        %Extract the current and previous elements in the row above
        a=o(i-1,j-1); %(previous)
        b=o(i-1,j);   %(current)
        %Assume that min()==0, so set c to max();
        c=a|b;
        %Now check if min()==1
        d=a&b;
        %If so, set c to L(1)
        c(d)=L(d);
        %Rotate L around only if min()==1
        L=circshift(L,-d);
        %And store c back to the output matrix
        o(i,j)=c;
    end;
end

Обновление: мне удалось оптимизировать оператор if-else, чтобы сэкономить несколько байтов. Формат ввода снова изменился на вектор столбцов.


1

Хаскелл, 153 149 байт

j[_]o l=(l,o)
j(a:u@(b:c))o q@(l:m)|a*b==0=j u(o++[a+b])q|1<2=j u(o++[l])m
k(r,a)=fmap((1:).(++[1]))$j a[]r
n%l=map snd$take n$iterate k(cycle l,[1])

%возвращает список битовых списков. Пример использования:

> 10 % [1,0,0,1] 
[[1],[1,1],[1,1,1],[1,0,0,1],[1,1,0,1,1],[1,1,1,1,1,1],[1,0,0,1,1,0,1],[1,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,0,1],[1,0,1,1,0,0,1,1,1,1]]

О, Боже! Нести случайный список Lвокруг - это чистая боль. Давайте посмотрим, может ли это быть короче.


1

C #, 152 байта

Здесь нет ничего особенного. Функция возвращает двумерный массив, где первый ранг - это строка, а второй - столбец.

Отступы и новые строки для ясности:

int[,]F(int n,int[]l){
    var o=new int[n,n];
    for(int y=0,x,i=0,m;y<n;y++)
        for(o[y,x=0]=1;x++<y;)
            o[y,x]=(m=o[y-1,x-1]+o[y-1,x])<2?m:l[i++%l.Length];
    return o;
}

1

TI-BASIC, 106 94 87 86 87 байтов

Prompt N,B
"∟B(1+remainder(𝑛,dim(∟B→u
{1
For(I,1,N
Disp Ans
augment({0},Ans)+augment(Ans,{0
Ans and Ans≠2+seq(u(𝑛-(Ans(X)<2)+2dim(∟B)),X,1,dim(Ans
End

У TI-BASIC нет оператора приращения, верно? Ну, вроде как. Переменная уравнения u, обычно используемая с последовательностями, имеет неясную особенность: когда uвызывается с аргументом, переменная𝑛 устанавливается на единицу больше, чем этот аргумент. Условное приращение зависит от этого. (Я ждал, чтобы использовать его в течение длительного времени.)

Для правильной работы индексации 𝑛должно быть значение по умолчанию 0, и𝑛Min умолчанию 1, поэтому либо очистите ОЗУ вашего калькулятора, либо установите эти значения вручную перед запуском.

augment({0},Ans)+augment(Ans,{0вычисляет список сумм двух соседних элементов, поэтому он возвращает список 0, 1 и 2. Тогда магия на этой линии:

Ans and Ans≠2+seq(u(𝑛-(Ans(X)≠2)+dim(∟B)),X,1,dim(Ans

Ans and                 ;set 0s to 0
Ans≠                    ;set to 0 all sums that equal...
2+
  seq(...,X,1,dim(Ans   ;execute for each element of the list
      u(                ;return this element in list of bits (looping)        
        𝑛               ;current location in the list
        -(Ans(X)≠2)+    ;subtract 1 if the element isn't 2
        2dim(∟B)        ;Add twice the dimension of the list
                           ;(because n<nMin on the first iteration, it's out of the domain
                           ;this prevents an error)
       )                      ;set n to one greater than that value
                              ;i.e. increment if element≠2
                        ;Will equal Ans(X) iff Ans(X)=2 and the bit read false

Результатом этой строки будет то, что элементы списка будут 0, если они были 0 или если они были 2, а считанный бит был 0.

Result of above line
n \ u |  0  |  1
0        0     0

Прецедент:

N=?7
B=?{0,1,0
             {1}
           {1 1}
         {1 0 1}
       {1 1 1 1}
     {1 1 0 0 1}
   {1 1 1 0 1 1}
 {1 0 0 1 1 1 1}
            Done
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.