A caminhada do bêbado quântico

69

É sabido que uma pessoa em uma grade sob a influência de álcool tem a mesma chance de seguir as direções disponíveis. No entanto, essa afirmação de bom senso não se aplica ao reino dos bêbados muito pequenos , cujo comportamento é como se eles seguissem todos os caminhos disponíveis ao mesmo tempo, e os possíveis caminhos que eles seguiam podem interferir um no outro. Sua tarefa é exibir as posições possíveis de um bêbado quântico após as netapas.

Especificação

O bêbado em questão ocupa uma grade quadrada e pode ser considerado um autômato celular de três estados usando uma vizinhança de Von Neumann (em forma de mais) que segue estas regras simples:

  • Emptyvai para Awakese for adjacente a exatamente um Awakee, caso contrário, vai paraEmpty
  • Awake vai para Sleeping
  • Sleeping vai para Sleeping

O estado inicial do quadro é um único Awakecercado por um campo infinito de Emptys.

Desafio

Dado um número inteiro não negativo n, crie uma representação ASCII do bêbado após as netapas. Cada estado deve ser representado por um caractere diferente, e as soluções devem indicar qual caractere significa qual estado. Se você usar espaços para Empty, não precisará incluir uma execução deles no final de uma linha.

Isso é , então a resposta mais curta vence. Aplicam-se brechas padrão , são permitidos espaços em branco à esquerda e à direita, saída de matriz de caracteres / matriz de caracteres 2D, etc.

Exemplos

Esses exemplos usam para Empty, @para Awakee #para Sleeping.

n=0
@

n = 1
 @
@#@
 @

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

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

n=6

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

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

Nota interessante

Observando a sequência do número de células ocupadas no OEIS, descobri que o bêbado quântico é isomórfico para a sequência de palitos de dente muito mais estudada . Se você puder incorporar esse conhecimento em um golfe melhor, ficarei impressionado.

stellatedHexahedron
fonte
11
Você pode verificar se o seu caso n=10está correto? Eu tentei algumas abordagens e todas obtiveram a mesma resposta (errada), então só quero ter certeza. Parece um pouco errado, mas eu não sei.
HyperNeutrino
4
@HyperNeutrino eu posso fazer melhor
stellatedHexahedron
11
É permitida uma matriz de caracteres unidimensional?
Jonathan Frech
4
Grande primeiro desafio, BTW!
Luis Mendo
11
@ PM2Ring válido. uma matriz numpy conta tanto quanto uma matriz nativa python no meu livro
stellatedHexahedron

Respostas:

34

Wolfram Language (Mathematica) , 92 91 bytes

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

Um desafio perfeito para usar o built-in do Mathematica CellularAutomaton!

Experimente online!

Vazio = 0, Despertado = 1, Dormindo = 2

Animação das primeiras 256 iterações (branco = vazio, cinza = acordado, preto = adormecido):

insira a descrição da imagem aqui

Explicação

CellularAutomaton[ ... ]

Executar CellularAutomatoncom especificações ...

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

Aplique a regra totalística de três cores 7049487784884, com a vizinhança de Von Neumann ...

{j={{1}},0}

Em uma placa com um único 1 no meio, com um fundo de 0s ...

{j#}

Repita os <input>tempos ( {j#}avalia para {{{#}}}). A matriz se expande automaticamente se uma célula fora da borda não for a mesma que o plano de fundo

7049487784884

Essa regra vem do número base 3 220221220221220221220221220, que significa "alterar tudo 1ou 2para 2, e mudar 0para 1se e somente se houver um número ímpar de 1s ao seu redor".

Print@@@

Imprima a matriz.

A semi-prova de "'ímpares 1' é equivalente a 'exatamente um 1'":

Considere essa grade de pixels 5x5. Branco é um 0ou uma 2célula (pixels não-acordado), e cinza é uma 1célula.

insira a descrição da imagem aqui

Se uma 1célula foi gerada em torno de três 0células, a grade deve ficar assim: possui três 1s organizados em forma de U (ou uma versão rotacionada) da seguinte maneira:

insira a descrição da imagem aqui

Devido à auto-similaridade desse autômato celular, qualquer padrão que apareça no autômato celular deve aparecer na diagonal (por indução). No entanto, esse padrão não é diagonalmente simétrico. isto é, não pode ocorrer na diagonal e não pode aparecer em nenhum lugar do autômato celular.

Despertar / Dormir são equivalentes

Observe que uma 0célula não pode ser cercada por exatamente uma ou três 2células e células de repouso 0, pois isso implicaria que, em alguns passos anteriores, a célula tinha um vizinho de uma ou três 1células - e já deve ter se transformado em uma 1(contradição). Portanto, não há problema em ignorar a distinção entre 1and 2e state 'altere tudo 1para 1e a 0para a 1se e somente se tiver um número ímpar de vizinhos diferentes de zero.'

O autômato celular resultante é realmente idêntico ao original, a única diferença é que não há distinção entre bêbados "acordados" e "adormecidos". Esse padrão é descrito em OEIS A169707 .

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

Experimente online!

Comparação lado a lado das 16 primeiras iterações:

insira a descrição da imagem aqui

A adição de duas iterações consecutivas fornece um resultado que segue as especificações do desafio (94 bytes):

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

Experimente online!

JungHwan Min
fonte
11

Python 2 , 192 bytes

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]

Experimente online!

-17 bytes graças ao Sr. Xcoder
-9 bytes usando o formato de saída de Jonathan
-11 bytes graças ao Lynn
-3 bytes graças ao ovs

HyperNeutrino
fonte
Mudar para um programa completo em que você pode usar execsalva 9 bytes e …for k in 0,1,2,3for…salva mais um: Link
Lynn
11
Na verdade, n=[C+k for k in-1j,1j,-1,1for C in c]economiza mais um byte!
Lynn
11
... ok, vou ter que admitir que X+Y*1jiné algo que eu realmente não pensei que fosse possível: P
ETHproductions
11
@ETHproductions Eu também não esperava que funcionasse, mas fiquei tipo "ei, você pode remover espaços depois de um número antes de um identificador / palavra-chave; portanto, se ele corresponder avidamente, funcionaria com números complexos?: D Python é incrível: P
HyperNeutrino
10

C, 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("");}}

As novas #definelinhas depois das não- linhas são apenas para apresentação aqui, portanto não são contadas. Eu incluí uma função wrapper, então é -6 (313) se a função não é contada e você assume que nvem de outro lugar. q(10)saídas:

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

Usando para vazio, "para dormir e !para acordado.

Isso funciona assim:

  • A(i,b,e)é “∀i∈ [b, e).”, B(b,e)é “∀r∈ [b, e) .∀c∈ [b, e).”

  • Observe que, após n gerações, o quadro é 2 n + 1 quadrado.

  • Devido à simetria do quadro, isso só precisa simular o quadrante inferior direito, portanto, alocamos uma matriz quadrada n + 1 com 1 linha e coluna de preenchimento para a pesquisa posterior do vizinho (então n + 2).

  • Alocar com callocpermite multiplicar simultaneamente a largura pela altura e limpar o quadro para 0(vazio).

  • Ao procurar uma célula por suas coordenadas ( Ce D), ela usa o valor absoluto da linha e coluna ( W) para espelhar automaticamente as coordenadas.

  • A placa é armazenada como uma matriz de pares de números inteiros que representam a geração atual e a anterior. Os números inteiros em questão são charpara que possamos evitar sizeof.

  • A geração pesquisada com mais frequência (pelo teste vizinho) é a geração anterior, portanto é colocada no índice 0 no par para que possa ser acessada *.

  • A cada geração ( g), a geração atual é copiada sobre a geração anterior usando um Bloop, e a nova geração é gerada a partir da antiga.

  • Cada célula é representada usando 0para vazio, 1para acordado e 2para dormir. A contagem de vizinhos era originalmente um cálculo do número de bits definido nos 4 bits inferiores da célula quando os 4 vizinhos eram deslocados e OR juntos como sinalizadores ( N), usados 16para dormir. Mas com a observação de que um número ímpar de vizinhos é equivalente a exatamente 1 vizinho, podemos salvar vários caracteres usando uma máscara com 1.

  • No final, o quadro é impresso por inteiro, iterando sobre o quadrante inferior direito, usando o mesmo truque de coordenadas de valor absoluto, menos o preenchimento para que não imprimamos o preenchimento externo no quadro. É também por isso que o Bloop inclui um colchete de abertura, porque temos a instrução extra de nova linha no loop externo.

  • Os códigos ASCII mapeiam convenientemente 0 + 32 (vazio) para um espaço, 2 + 32 (adormecido) para "e 1 + 32 (acordado) para !.

Em suma, acho que este é um golfe surpreendentemente legível por causa da boa estrutura do problema.

Jon Purdy
fonte
Uau. Coisa pequena, mas acho que você pode economizar mais alguns bytes, substituindo as mudanças com a multiplicação e putchar(10)computs("")
undercat
11
@undercat: Obrigado! Adicionado à resposta. Às vezes, concentro-me tanto em reduzir algumas coisas que sinto falta de outras vitórias que são óbvias assim que alguém as aponta.
Jon Purdy
343 bytes .
Jonathan Frech
@ JonathanFrech: Obrigado, adicionado. Esqueci que a contagem de vizinhos pode usar um NAND.
Jon Purdy
@ JonathanFrech: Desculpe, acho que isso não estava claro. &~não é um NAND, eu quis dizer que, às vezes, penso !(a &~ b)em termos de a NAND (NOT b), embora neste caso a lógica !não seja a mesma que a bit a bit, ~porque estamos confiando no resultado 0ou 1no !.
perfil completo de Jon Purdy
6

MATL , 39 bytes

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

Isso exibe

  • Emptycomo (espaço)
  • Awake Como #
  • Sleepingcomo !.

Experimente online! Você também pode observar o padrão crescer na arte ASCII ou graficamente (código modificado).

Explicação

O código utiliza números complexos 0, 1, jpara representar os três estados: vazio, acordar, dormir, respectivamente.

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
Luis Mendo
fonte
5

Befunge, 384 304 bytes

&: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*+^

Experimente online!

O problema de tentar implementar esse tipo de coisa no Befunge é o tamanho limitado da memória (2000 bytes para dados e código). Então, eu tive que usar um algoritmo que calcula o caractere correto para qualquer coordenada, sem referência aos cálculos anteriores. Consegue isso olhando recursivamente no tempo em todos os caminhos possíveis que o bêbado pode ter seguido para chegar a esse ponto.

Infelizmente, essa não é uma solução eficiente específica. Funciona, mas é incrivelmente lento e se torna exponencialmente mais lento quanto maior o valor de n . Portanto, embora possa funcionar para n até 127 (limite de células de memória de 7 bits da Befunge), na prática, você inevitavelmente perderá o interesse aguardando o resultado. No TIO, atingirá o tempo limite de 60 segundos em algo maior que cerca de 6 (no máximo). Um compilador terá um desempenho muito melhor, mas mesmo assim você provavelmente não gostaria de ir muito acima de 10.

Ainda assim, achei que valeu a pena enviar, porque na verdade é uma demonstração bastante agradável de uma "função" recursiva no Befunge.

James Holderness
fonte
4

Python 2 , 214 bytes

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)]

Experimente online!

Explicação

Usa 0para empty, 1para sleepinge 2para awake. Imprime uma lista de caracteres bidimensionais (seqüências de um comprimento).
Define uma função que recebe um número inteiro não negativo n. Avança sucessivamente o autômato celular até que o estado desejado seja alcançado. Por fim, é aplicada uma conversão entre os valores inteiros internos e os caracteres reais.

Jonathan Frech
fonte
4

Lua , 251 242 239 238 bytes

-8 bytes, simplificando o inicializador de matriz ao custo de alguns espaços em branco iniciais adicionais.
-1 byte mudando c=i==2+...and print(s)para c=i~=2+...or print(s).
-3 bytes, construindo uma sequência completa primeiro e imprimindo uma vez no final.
-1 byte, graças a Jonathan Frech , reescrevendo or(g(...)==1 andcomo 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)

Experimente online!

Vazio = Espaço
Despertado = 1
Dormindo =0

Pega a entrada da linha de comando e imprime em stdout.

Representando os estados como false/ nil, 1e 0internamente, a detecção de "vazio" não precisa de nenhum código eo "exatamente um acordado" cheque pode ser feito com apenas uma adição.

Jonathan S.
fonte
Eu acho que or(g(...)==1 andpode ser or(1==g(...)and.
Jonathan Frech
4

Geléia , 39 29 bytes

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

Experimente online!

Usos 0, 1e 2para vazio acordado e dormindo. O rodapé no link converte isso em , @e #.

  • -1 byte usando em ṬŒḄvez de ḤḶ=¹.
  • -2 bytes usando em -vez de 1N. Também torna ¤desnecessário.
  • -1 byte usando em Svez de +/.
  • -6 bytes usando em Ḃ+Ḃ+vez de %3=1+=1Ḥ$+. Agora usa 2para dormir em vez de 3.

Explicação chegando ...

dylnan
fonte
4

APL (Dyalog Classic) , 38 bytes

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

Experimente online!

com base na solução de Erik the Outgolfer

⍪1 é uma matriz 1x1 contendo 1

entrada avaliada

( )⍣⎕ aplique isso muitas vezes

  • (⌽0,⍉)⍣4cercar com 0s, ou seja, 4 vezes: transpose ( ), adicione 0s à esquerda ( 0,), inverta horizontalmente ( )

  • g←3+/0,,∘0 uma função que soma triplos horizontais, chame-a g

  • ⍉∘g∘⍉uma função que soma triplos verticais - que está gem transposição

  • 2 | ⍉∘g∘⍉ + g←3+/0,,∘0 soma das duas somas módulo 2

  • quanto maior entre isso e ...

  • 2∘∧ o LCM de 2 e a matriz original - isso transforma 1s em 2s, preservando 0s e 2s

ngn
fonte
3

Perl 5 , 192 + 1 ( -n) = 193 bytes

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

Experimente online!

Usa 0 para vazio, 1 para acordado e 2 para adormecido.

Xcali
fonte
3

Ruby , 164 153 bytes

->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*""}

Experimente online!

Usa "" para Vazio, "@" para Desperta e "#" para Dormir (como no exemplo). Eu poderia salvar 6 bytes usando números, suponho, mas parece melhor assim.

iamnotmaynard
fonte
2

Pip , 69 61 bytes

60 bytes de código, +1 para -lsinalizador.

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

Toma ncomo argumento da linha de comando. Usa 0para vazio, 1para acordado e 2para dormir. (Para obter uma melhor arte ASCII, como nos exemplos do desafio, substitua a final ypor " @#"@y.)

Experimente online!

Explicação

Configuração:

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

Laço principal:

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

onde o corpo da função é:

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

Após o loop, simplesmente imprimimos automaticamente y. O -lsinalizador significa que a lista aninhada é impressa concatenando o conteúdo de cada linha e separando as linhas com novas linhas.

DLosc
fonte
2

Java (OpenJDK 8) , 220 bytes

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;}

Experimente online!

Nota: a matriz retornada contém uma borda ou '\0'caracteres. Como o plano deve ser infinito, apenas não-borda é usada.

Mapeamento de caracteres:

  • Vazio: (espaço)
  • Acordado: =
  • Adormecido: 0

Economizar

  • 29 bytes salvos graças a Jonathan S.
  • 9 bytes adicionais graças a Jonathan S. trocando caracteres com os outros e "fazendo mágica com números primos e aritmética modular"
Olivier Grégoire
fonte
11
229 bytes.
Jonathan S.
Obrigado @JonathanS. Eu estava procurando muito melhorar meu @cheque e você encontrou a chave! Agradável. A chartransmissão foi uma supervisão total minha.
Olivier Grégoire
11
220 bytes fazendo mágica com números primos e aritmética modular.
Jonathan S.
Esse é um pensamento muito bom!
Olivier Grégoire
11
Obrigado! Acabei de encontrar uma versão mais bonita que também tem 220 bytes, módulo diferente.
Jonathan S.
2

Python, 199 192 bytes

Esse código é executado no Python 2 e no Python 3, mas usa a popular biblioteca Numpy de terceiros para manipular a matriz.

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

Vazio = 0
Despertado = 1
Dormindo = 2

print(f(6)) saídas

[[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]]

Se você deseja uma impressão mais bonita, pode chamá-lo desta maneira:

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

que imprime usando os mesmos caracteres indicados na pergunta.

PM 2Ring
fonte
Não sei se a saída de uma matriz inteira é permitida, pois [e]ach state should be represented by a different character(eu interpreto charactercomo um caractere ASCII real, em vez de um número inteiro).
Jonathan Frech
@JonathanFrech Fair call. Vou perguntar ao OP.
PM 2Ring