Квантовая Пьяная Прогулка

69

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

Спецификация

Рассматриваемый пьяница занимает квадратную сетку и может рассматриваться как клеточный автомат с 3 состояниями, использующий окрестность фон Неймана (в форме плюса), которая следует этим простым правилам:

  • Emptyидет к тому, Awakeесли он находится рядом с ровно одним Awake, а в противном случае идет кEmpty
  • Awake идет к Sleeping
  • Sleeping идет к Sleeping

Начальное состояние доски - это одно Awakeокружение, окруженное бесконечным полем Emptys.

Вызов

Учитывая неотрицательное целое число n, создайте представление ASCII пьяницы после nшагов. Каждое состояние должно быть представлено другим символом, и в решениях должно быть указано, какой символ означает какое состояние. Если вы используете пробелы для Empty, вам не нужно включать их в конце строки.

Это , поэтому выигрывает самый короткий ответ. Применяются стандартные лазейки , разрешены пробелы в начале и в конце, разрешен вывод строкового массива / двумерного массива и т. Д.

Примеры

Эти примеры используют для Empty, @для Awakeи #для Sleeping.

n=0
@

n = 1
 @
@#@
 @

n = 2
  @
  #
@###@
  #
  @

n = 3
   @
  @#@
 @ # @
@#####@
 @ # @
  @#@
   @

n=6

      @
      # 
    @###@
     @#@  
  @  ###  @
  #@# # #@#
@###########@
  #@# # #@#
  @  ###  @
     @#@
    @###@
      #
      @

n=10
          @
          #
        @###@
         @#@
         ###
        # # #
       #######
      #  ###  #
  @  ##  ###  ##  @
  #@# ### # ### #@#
@###################@
  #@# ### # ### #@#
  @  ##  ###  ##  @
      #  ###  #
       #######
        # # #
         ###
         @#@
        @###@
          #
          @

Интересная заметка

Посмотрев последовательность числа занятых клеток в OEIS, я обнаружил, что квантовый пьяница изоморфен гораздо лучше изученной последовательности зубочисток . Если вы сможете использовать эти знания в лучшем гольфе, я буду приятно удивлен.

stellatedHexahedron
источник
1
Можете ли вы проверить, чтобы убедиться, что ваше дело n=10правильно? Я попробовал несколько подходов, и все они получают один и тот же (неправильный) ответ, поэтому я просто хочу убедиться. Это выглядит немного странно, но я не знаю.
HyperNeutrino
4
@HyperNeutrino Я могу сделать тебя лучше
звездный
1
Разрешен ли одномерный массив символов?
Джонатан Фрех
4
Отличный первый вызов, кстати!
Луис Мендо
1
@ PM2Ring действителен. NumPy массив насчитывает столько же , сколько родной массив питона в моей книге
stellatedHexahedron

Ответы:

34

Wolfram Language (Mathematica) , 92 91 байт

Print@@@CellularAutomaton[{7049487784884,{3,{a={0,3,0},3-2a/3,a}},{1,1}},{j={{1}},0},{j#}]&

Идеальный вызов, чтобы использовать встроенную Mathematica CellularAutomaton!

Попробуйте онлайн!

Пустой = 0, Пробужденный = 1, Спящий = 2

Анимация первых 256 итераций (белый = пустой, серый = активный, черный = спящий):

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

объяснение

CellularAutomaton[ ... ]

Запустите CellularAutomatonсо спецификациями ...

{7049487784884,{3,{a={0,3,0},3-2a/3,a}},{1,1}}

Примените трехцветное тоталистическое правило 7049487784884 с окрестностью фон Неймана ...

{j={{1}},0}

На доске с одним 1 посередине, с фоном 0s ...

{j#}

Повторите <input>раз ( {j#}оценивает {{{#}}}). Массив автоматически расширяется, если ячейка за пределами границы не совпадает с фоном

7049487784884

Это правило взято из числа base-3 220221220221220221220221220, что означает «изменить все 1или 2на 2и изменить 0на 1тогда и только тогда, когда 1вокруг него нечетное число s».

Print@@@

Распечатать массив.

Полу-доказательство «нечетного 1» эквивалентно «ровно одному 1»:

Рассмотрим эту 5x5 сетку пикселей. Белый - это 0или 2ячейка (не пробужденные пиксели), а серый - это 1ячейка.

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

Если 1ячейка была сгенерирована вокруг трех 0ячеек, то сетка должна выглядеть следующим образом: она имеет три 1s, расположенных в форме буквы U (или повернутую версию), следующим образом:

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

Из-за самоподобия этого клеточного автомата любая фигура, которая появляется в клеточном автомате, должна появляться на диагонали (по индукции). Однако этот рисунок не является диагонально симметричным. то есть это не может произойти по диагонали и не может появиться где-нибудь на клеточном автомате.

Пробуждение / Спящий эквивалент

Обратите внимание, что 0ячейка не может быть окружена ровно одной или тремя 2ячейками и остальными 0ячейками, поскольку это подразумевало бы, что за несколько шагов до этого ячейка имела соседа из одной или трех 1ячеек - и, должно быть, уже превратилась в 1(противоречие). Следовательно, можно игнорировать различие между 1и 2и состоянием «измените все 1на 1, и a 0на a, 1если и только если у него нечетное число ненулевых соседей».

Получающийся в результате клеточный автомат действительно идентичен оригиналу, единственное отличие состоит в том, что нет различий между «проснувшимися» и «спящими» пьяницами. Этот шаблон описан в OEIS A169707 .

Print@@@CellularAutomaton[{750,{2,{a={0,2,0},2-a/2,a}},{1,1}},{j={{1}},0},{j#}]&

Попробуйте онлайн!

Параллельное сравнение первых 16 итераций:

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

Добавление двух последовательных итераций дает результат, соответствующий спецификациям вызова (94 байта):

Print@@@Plus@@CellularAutomaton[{750,{2,{a={0,2,0},2-a/2,a}},{1,1}},{{{1}},0},{Ramp@{#-1,#}}]&

Попробуйте онлайн!

Юнг Хван Мин
источник
11

Python 2 , 192 байта

x=input()
o=c={x+x*1j}
R=range(x-~x)
exec"n=[C+k for k in-1j,1j,-1,1for C in c];n={k for k in n if(k in o)<2-n.count(k)};o|=c;c=n;"*x
print[[`(X+Y*1jin c)+(X+Y*1jin o|c)`for Y in R]for X in R]

Попробуйте онлайн!

-17 байт благодаря Mr. Xcoder
-9 байт с использованием выходного формата Джонатана
-11 байт благодаря Lynn
-3 байт благодаря ovs

HyperNeutrino
источник
Переключение на полную программу, где вы можете использовать, execсохраняет 9 байтов и …for k in 0,1,2,3for…сохраняет еще один: Ссылка
Линн
1
На самом деле, n=[C+k for k in-1j,1j,-1,1for C in c]сохраняет еще один байт!
Линн
1
... хорошо, я должен признать X+Y*1jin, что я действительно не думал, что это возможно: P
ETHproductions
1
@ETHproductions Я тоже не ожидал, что это сработает, но мне показалось, что «эй, вы можете удалить пробелы после числа перед идентификатором / ключевым словом, поэтому, если он будет соответствовать жадному совпадению, он будет работать со сложными числами?»: «Python потрясающий: P»
HyperNeutrino
10

С 360 354 343 319

#define A(i,b,e)for(int i=b;i<e;++i)
#define B(b,e)A(r,b,e){A(c,b,e)
#define W(n)(n<0?-(n):n)
#define C(r,c)b[W(r)*s+W(c)]
#define D C(r,c)

q(n){char N,s=n+2,(*b)[2]=calloc(s,2*s);C(0,0)
[1]=1;A(g,0,n+1){B(0,s)*D=D[1];}B(0,g+2){N=(*C
(r-1,c)+*C(r+1,c)+*C(r,c-1)+*C(r,c+1))&1;D[1]=
*D?2:N;}}}B(2-s,s-1)putchar(*D+32);puts("");}}

Символы новой #defineстроки после строк не предназначены для представления здесь, поэтому они не учитываются. Я включил функцию-обертку, так что это −6 (313), если функция не считается, и вы предполагаете, что она nпришла откуда-то еще. q(10)выходы:

          !          
          "          
        !"""!        
         !"!         
         """         
        " " "        
       """""""       
      "  """  "      
  !  ""  """  ""  !  
  "!" """ " """ "!"  
!"""""""""""""""""""!
  "!" """ " """ "!"  
  !  ""  """  ""  !  
      "  """  "      
       """""""       
        " " "        
         """         
         !"!         
        !"""!        
          "          
          !          

Использование для пустых, "для сна и !для бодрствования.

Это работает так:

  • A(i,b,e)«∀i∈ [b, e).», B(b,e)«∈r∈ [b, e) .∀c∈ [b, e).»

  • Обратите внимание, что после n поколений, доска составляет 2 n + 1 квадрат.

  • Из-за симметрии доски это нужно только для имитации нижнего правого квадранта, поэтому мы выделяем n + 1 квадратную матрицу с 1 строкой и столбцом заполнения для последующего поиска соседей (так что n + 2).

  • Выделение с помощью callocпозволяет нам одновременно умножить ширину на высоту и очистить доску до 0(пусто).

  • При поиске ячейки по ее координатам ( Cи D) она использует абсолютное значение строки и столбца ( W) для автоматического отражения координат.

  • Доска хранится в виде массива пар целых чисел, представляющих текущее и предыдущее поколения. Рассматриваемые целые числа таковы, charчто мы можем избежать sizeof.

  • Поколение, которое чаще всего просматривалось (по тесту соседей), относится к прошлому, поэтому оно помещается в индекс 0 в паре, поэтому к нему можно получить доступ *.

  • При каждом поколении ( g) текущее поколение копируется поверх предыдущего поколения с использованием Bцикла, затем новое поколение генерируется из старого.

  • Каждая ячейка представлена ​​как 0для пустой, 1для бодрствования, так и 2для сна. Подсчет соседей первоначально был вычислением количества битов, установленных в младших 4 битах ячейки, когда эти 4 соседа сдвинуты и ИЛИ вместе как flags ( N), используя 16для ожидания. Но с учетом того, что нечетное число соседей эквивалентно ровно одному соседу, мы можем сохранить несколько символов, просто используя маску с 1.

  • В конце доска печатается полностью путем итерации по нижнему правому квадранту, используя тот же трюк координат абсолютного значения, минус отступы, поэтому мы не печатаем внешние отступы на доске. Именно поэтому Bцикл включает в себя открывающую фигурную скобку, потому что у нас есть дополнительный оператор новой строки во внешнем цикле.

  • Коды ASCII удобно отображают 0 + 32 (пусто) в пробел, 2 + 32 (спит) в "и 1 + 32 (в пробуждении) в !.

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

Джон Перди
источник
Ух ты. Крошечная вещь, но я думаю , что вы можете сэкономить еще несколько байт, заменяя сдвиги с умножением и putchar(10)сputs("")
undercat
1
@undercat: спасибо! Добавил в ответ. Иногда я сосредотачиваюсь на том, чтобы уменьшить некоторые вещи настолько, что пропускаю другие победы, которые очевидны, как только кто-то указывает на них.
Джон Пурди
343 байта .
Джонатан Фрех
@JonathanFrech: Спасибо, добавил. Я забыл, что для подсчета соседей можно использовать NAND.
Джон Пурди
@JonathanFrech: Извините, я думаю, это было неясно. &~это не NAND, я имел в виду, что иногда я думаю о !(a &~ b)терминах a NAND (NOT b), хотя в данном случае логика !не совпадает с побитовой, ~потому что мы полагаемся на результат 0или 1результат !.
Джон Пурди
6

MATL , 39 байт

QtE:=&*G:"tt0=w1Y6Z+Xj1=*w|gJ*+]Q|U31+c

Это отображает

  • Emptyкак (пробел)
  • Awake как #
  • Sleepingкак !.

Попробуйте онлайн! Вы также можете наблюдать рост рисункав ASCII-графике или графически (измененный код).

объяснение

Код использует комплексные числа 0, 1, jчтобы представить три состояния: пустые, поминки, спать соответственно.

Q         % Implicitly input n. Add 1
tE        % Duplicate and multiply by 2
:         % Range [1 2 ... 2*n]
=         % Test for equalty. Gives [0 ... 0 1 0... 0], with 1 at position n
&*        % Matrix of all pairwise products. Gives square matrix of size 2*n
          % filled with 0, except a 1 at position (n,n). This is the grid
          % where the walk will take place, initiallized with an awake cell
          % (value 1). The grid is 1 column and row too large (which saves a
          % byte)
G:"       % Do n times
  tt      %   Duplicate current grid state twice
  0=      %   Compare each entry with 0. Gives true for empty cells, false
          %   for the rest
  w       %   Swap: moves copy of current grid state to top
  1Y6     %   Push 3×3 matrix with Von Neumann's neighbourhood
  Z+      %   2D convolution, maintaining size
  Xj      %   Real part
  1=      %   Compare each entry with 1. This gives true for cells that
          %   have exactly 1 awake neighbour
  *       %   Multiply, element-wise. This corresponds to logical "and": 
          %   cells that are currently empty and have exactly one awake
          %   neighbour. These become 1, that is, awake
  w       %   Swap: moves copy of current grid state to top
  |g      %   Absolute value, convert to logical: gives true for awake or
          %   sleeping cells, false for empty cells
  J*+     %   Mulltiply by j and add, element-wise. This sets awake and 
          %   sleeping cells to sleeping. The grid is now in its new state
]         % End
Q         % Add 1, element-wise. Transforms empty, awake, sleeping 
          % respectively from 0, 1, j into 1, 2, 1+j
|U        % Abolute value and square, element-wose. Empty, awake, sleeping 
          % respectively give 1, 4, 2
31+c      % Add 31 element-wise and convert to char. Empty, awake, sleeping 
          % respectively give characters ' ' (codepoint 32), '#' (codepoint 
          % 35) and '!' (codepoint 33). Implicitly display
Луис Мендо
источник
5

Befunge, 384 304 байта

&:00p->55+,000g->>00g30p:40p\:50p\5>>40g!50g!*vv0g05g04p03-<
@,+55_^#`g00:+1$_^>p:4+4g5%2-50g+5#^0#+p#1<v03_>30g:!#v_:1>^
#v_>$99g,1+:00g`^ ^04+g04-2%5g4:\g05\g04\p<>g!45*9+*3+v>p:5-
 >\50p\40p\30p:#v_>>0\99g48*`!>v >30g:1-30^>>**\!>#v_>v^9 9<
$0\\\\0$        >\99g88*-!+\:4->#^_\>1-!48>^       >$3>48*+^

Попробуйте онлайн!

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

К сожалению, это не очень эффективное решение. Это работает, но невероятно медленно, и становится экспоненциально медленнее, чем больше значение n . Таким образом, хотя он потенциально может работать для любого n, вплоть до 127 (предел ячейки памяти 7-битной памяти Befunge), на практике вы неизбежно потеряете интерес в ожидании результата. На TIO тайм-аут на 60 секунд превысит 6 (в лучшем случае). Компилятор будет работать намного лучше, но даже тогда вы, вероятно, не захотите идти намного выше 10.

Тем не менее, я подумал, что это стоило представить, потому что это действительно хорошая демонстрация рекурсивной «функции» в Befunge.

Джеймс Холдернесс
источник
4

Python 2 , 214 байтов

def f(n):k=n-~n;N=k*k;A=[0]*N;A[N/2]=2;exec"A=[[2*([j%k>0and A[j-1],j%k<k-1and A[j+1],j/k>0and A[j-k],j/k<k-1and A[j+k]].count(2)==1),1,1][v]for j,v in enumerate(A)];"*n;print[map(str,A)[k*x:][:k]for x in range(k)]

Попробуйте онлайн!

объяснение

Использует 0для empty, 1для sleepingи 2для awake. Распечатывает список двумерных символов (строки одной длины).
Определяет функцию, которая принимает неотрицательное целое число n. Успешно продвигает клеточный автомат, пока не будет достигнуто желаемое состояние. Наконец, выполняется преобразование между внутренними целочисленными значениями и фактическими символами.

Джонатан Фрех
источник
4

Lua , 251 242 239 238 байт

-8 байт за счет упрощения инициализатора массива за счет дополнительных начальных пробелов.
-1 байт, переходя c=i==2+...and print(s)в c=i~=2+...or print(s).
-3 байта, сначала собрав полную строку и напечатав один раз в конце.
-1 байт благодаря Джонатану Фреху , переписав or(g(...)==1 andкак or(1==g(...)and.

function g(x,y)return(a[x]or{})[y]or 0 end a={{1}}for i=2,2+...do n={}s=""for x=-i,i do n[x]=n[x]or{}q=a[x]or{}for y=-i,i do n[x][y]=q[y]and 0or(1==g(x+1,y)+g(x,y+1)+g(x-1,y)+g(x,y-1)and 1)s=s..(q[y]or" ")end s=s.."\n"end a=n end print(s)

Попробуйте онлайн!

Пусто =
Пробуждение = 1
Спящий =0

Принимает ввод из командной строки и печатает на стандартный вывод.

Представляя состояния , как false/ nil, 1и 0внутренне, обнаруживая «пустой» не нуждается в какой - либо код , и «точно один бодрствует» проверка может быть сделано только с добавлением.

Джонатан С.
источник
Я думаю, что or(g(...)==1 andможет быть or(1==g(...)and.
Джонатан Фрех
4

Желе , 39 29 байт

-,1ṙ@€Sµ+Z
‘ṬŒḄ×þ`µÇ׬Ḃ+Ḃ+µ³¡

Попробуйте онлайн!

Использует 0, 1и 2для пустой бодрствует и спит. Сноска в ссылке преобразует это , @и #.

  • -1 байт, используя ṬŒḄвместо ḤḶ=¹.
  • -2 байта, используя -вместо 1N. Также делает ¤ненужным.
  • -1 байт, используя Sвместо +/.
  • -6 байт, используя Ḃ+Ḃ+вместо %3=1+=1Ḥ$+. Теперь использует 2для сна вместо 3.

Объяснение идет ...

dylnan
источник
4

APL (Dyalog Classic) , 38 байт

((2∘∧⌈2|⍉∘g∘⍉+g3+/0,,∘0)(⌽0,⍉)⍣4)⍣⎕⍪1

Попробуйте онлайн!

на основе решения Эрика Аутгольфера

⍪1 матрица 1x1, содержащая 1

проверенный ввод

( )⍣⎕ применять это много раз

  • (⌽0,⍉)⍣4окружить 0, то есть 4 раза: transpose ( ), добавить 0 слева ( 0,), повернуть по горизонтали ( )

  • g←3+/0,,∘0 функция, которая суммирует горизонтальные тройки, назовите ее g

  • ⍉∘g∘⍉функция, которая суммирует вертикальные тройки - это gпод транспозицией

  • 2 | ⍉∘g∘⍉ + g←3+/0,,∘0 сумма двух сумм по модулю 2

  • чем больше между этим и ...

  • 2∘∧ LCM 2 и исходная матрица - это превращает 1 с в 2 с, сохраняя 0 и 2

СПП
источник
3

Perl 5 , 192 + 1 ( -n) = 193 байта

for$i(1..2*$_+1){push@a,[()x$_]}$a[$_][$_]=1;map{@b=();for$i(0..$#a){map$b[$i][$_]=$a[$i][$_]?2:$a[$i-1][$_]+($_&&$a[$i][$_-1])+$a[$i+1][$_]+$a[$i][$_+1]==1?1:0,0..$#a}@a=@b}1..$_;say@$_ for@a

Попробуйте онлайн!

Использует 0 для пустого, 1 для бодрствующего и 2 для спящего.

Xcali
источник
3

Рубин , 164 153 байта

->n{(r=([e=' ']*(l=2*n+1)<<"
")*l)[n+n*l+=1]=a=?@
n.times{r=r.map.with_index{|c,i|c==a ??#:c==e ?r.values_at(i-1,i+1,i-l,i+l).one?{|v|v==a}?a:e:c}}
r*""}

Попробуйте онлайн!

Использует "" для пустого, "@" для пробуждения и "#" для сна (как в примере). Полагаю, я мог бы сэкономить 6 байтов, используя вместо этого числа, но это выглядит лучше.

iamnotmaynard
источник
2

Пип , 69 61 байт

60 байтов кода, +1 за -lфлаг.

YZG2*a+1y@a@a:1LaY{y@a@b?2oN(y@(a+_)@(b+B)MP[0o0v0])=1}MC#yy

Принимает nв качестве аргумента командной строки. Используется 0для пустых, 1для бодрствования и 2для сна. (Чтобы получить более качественный ASCII-арт, как в примерах задания, замените финал yна " @#"@y.)

Попробуйте онлайн!

объяснение

Настроить:

YZG2*a+1y@a@a:1

                 Implicit: a is 1st cmdline arg; o is 1; v is -1
 ZG2*a+1         Square grid (i.e. nested list) of 0's, with side length 2*a+1
Y                Yank into y variable
        y@a@a:1  Set the element at coordinates (a,a) to 1

Основной цикл:

LaY{...}MC#y

La            Loop (a) times:
          #y  Len(y) (i.e. 2*a+1)
   {   }MC    Map this function to the coordinate pairs in a 2*a+1 by 2*a+1 grid
  Y           and yank the resulting nested list back into y

где тело функции:

y@a@b?2oN(y@(a+_)@(b+B)MP[0o0v0])=1

                                     The function args, representing the coords of the
                                     current cell, are a and b
y@a@b?                               Is the cell at these coords 0 or nonzero?
      2                              If nonzero (1 or 2), make it 2
                                     Else, if zero, we need to check the neighbors
                         [0o0v0]     List of [0; 1; 0; -1; 0]
                       MP            Map this function to each adjacent pair of values--
                                     i.e. call it four times with args (0; 1), (1; 0),
                                     (0; -1), and (-1; 0)
          y                           Index into the grid using
           @(a+_)                     a + the 1st item in the pair as the row and
                 @(b+B)               b + the 2nd item in the pair as the column
                                     The result of MP is a list of the values of the cells
                                     in the Von Neumann neighborhood
       oN(                      )    Get the number of 1's in that list
                                 =1  and test if it equals 1
                                     If so, the new value of this cell is 1; if not, it's 0

После цикла мы просто автопечать y. -lФлаг означает , что вложенный список печатается путем конкатенации содержимого каждой строки и разделяя строки с символами новой строки.

DLosc
источник
2

Java (OpenJDK 8) , 220 байт

n->{int s=n*2+3,i=0,x,y;char[][]a=new char[s][s],b;for(a[s/2][s--/2]=61;i++<n;a=b)for(b=new char[s+1][s+1],x=0;++x<s;)for(y=0;++y<s;)b[x][y]=a[x][y]>32?'0':(a[x][y-1]+a[x][y+1]+a[x-1][y]+a[x+1][y])%8==5?61:' ';return a;}

Попробуйте онлайн!

Примечание: возвращаемый массив содержит границу или '\0'символы. Поскольку предполагается, что плоскость бесконечна, используется только не граница.

Отображение символов:

  • Пусто: (пробел)
  • Awake: =
  • Спать: 0

Сохраняет

  • 29 байтов сэкономлено благодаря Джонатану С.
  • Еще 9 байтов благодаря Джонатану С., меняя символы с другими и «делая магию с простыми числами и модульной арифметикой»
Оливье Грегуар
источник
1
229 байт.
Джонатан С.
Спасибо @JonathanS. Я очень старался улучшить свою @проверку, и вы нашли ключ! Приятно. charЛитой был полный контроль со мной.
Оливье Грегуар
1
220 байтов , делая магию с простыми числами и модульной арифметикой.
Джонатан С.
Это очень хорошее мышление!
Оливье Грегуар
1
Спасибо! Я только что нашел более красивую версию, которая также 220 байтов, другой модуль.
Джонатан С.
2

Python, 199 192 байта

Этот код работает как на Python 2, так и на Python 3, но он использует популярную стороннюю библиотеку Numpy для обработки массива.

from numpy import*
def f(n):
 m=2*n+1;g=zeros((m+2,)*2,'i');g[n+1,n+1]=1
 while n:a=g[1:-1,1:-1];a[:]=(a<1)*(sum(g[r:r+m,c:c+m]&1for r,c in((0,1),(1,0),(1,2),(2,1)))==1)+(a>0)*2;n-=1
 return g

Пустой = 0
Пробужденный = 1
Спящий = 2

print(f(6)) выходы

[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 2 0 0 0 0 0 0 0]
 [0 0 0 0 0 1 2 2 2 1 0 0 0 0 0]
 [0 0 0 0 0 0 1 2 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 2 2 2 0 0 1 0 0 0]
 [0 0 0 2 1 2 0 2 0 2 1 2 0 0 0]
 [0 1 2 2 2 2 2 2 2 2 2 2 2 1 0]
 [0 0 0 2 1 2 0 2 0 2 1 2 0 0 0]
 [0 0 0 1 0 0 2 2 2 0 0 1 0 0 0]
 [0 0 0 0 0 0 1 2 1 0 0 0 0 0 0]
 [0 0 0 0 0 1 2 2 2 1 0 0 0 0 0]
 [0 0 0 0 0 0 0 2 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Если вы хотите более красивую печать, вы можете назвать это так:

n=6;print('\n'.join(''.join(' @#'[v]for v in u)for u in f(n)))

который печатает, используя те же символы, что и в вопросе.

PM 2Ring
источник
Я не знаю, разрешен ли вывод целочисленной матрицы как [e]ach state should be represented by a different character(я интерпретирую characterкак фактический символ ASCII, а не как целое число).
Джонатан Фрех
@JonathanFrech Справедливый звонок. Я спрошу ОП.
PM 2Ring