Autómata celular pseudoaleatorio


14

Introducción

En este desafío, simularemos un cierto autómata celular probabilístico usando números pseudoaleatorios muy malos. El autómata celular se define en cadenas binarias mediante la siguiente regla local. Suponga que el vecino izquierdo de una celda y la celda misma tienen estados ay b.

  • Si min(a,b) == 0, entonces el nuevo estado de bes max(a,b).
  • Si min(a,b) == 1, entonces el nuevo estado de bse elige aleatoriamente {0,1}.

La siguiente imagen muestra una posible evolución de 10 pasos de un solo 1.

1
11
101
1111
11001
101011
1111111
10001001
110011011
1010111101

Tenga en cuenta cómo dos 1s adyacentes a veces evolucionan hacia 1, y a veces hacia 0, y los bits más al borde siempre son 1s. Su tarea es producir una evolución del autómata celular de esta forma.

Entradas

Sus entradas son un número entero positivo n, que denota el número de filas para mostrar, y una lista no vacía de bits L, que utilizamos como fuente de aleatoriedad.

Salida

Su salida es una lista de listas o una matriz de bits 2D, que representa la evolución de un solo paso 1de ntiempo, como en la figura anterior. Puede rellenar la salida con 0s para obtener filas de igual longitud, si lo desea, pero no debe haber 0s iniciales .

Las elecciones aleatorias en el autómata celular se deben extraer de la lista L, volviendo al principio cuando se agota. Más explícitamente, si la salida se recorre de una fila a la vez de arriba a abajo, de izquierda a derecha, las sucesivas elecciones aleatorias formarán la lista Lrepetida tantas veces como sea necesario.

Ejemplo

Supongamos que las entradas son n = 7y L = [0,1,0]. Luego, el autómata celular evoluciona de la siguiente manera durante los 7 pasos, donde hemos puesto un vderecho sobre cada elección aleatoria:

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

Si leemos todos los bits marcados con a v, obtenemos 01001001, que se Lrepite 2,66 veces. El siguiente bit aleatorio sería 0.

Reglas y puntuación

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana, y las lagunas estándar no se permiten. El formato exacto de las entradas y salidas no es importante (dentro de lo razonable).

Casos de prueba

Versión determinista, cada bit aleatorio es 0:

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

Cada bit aleatorio es 1:

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

Versiones pseudoaleatorias:

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

Respuestas:


3

Pyth, 33 bytes

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

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación:

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

Retina , 139 bytes

^.
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>

Donde <empty>indica que hay una línea vacía final. Cada línea va en un archivo separado y #debe reemplazarse con avances de línea (0x0A).

Espera que la entrada esté nen unario (hecho de ceros, como en Unario ), seguido de un espacio, seguido de la cadena "pseudoaleatoria", por ejemplo 10, [1, 0, 0, 1], se leería como

0000000000 1001

La salida es como en el desafío, pero rellena con ceros, p. Ej.

1000000000
1100000000
1110000000
1001000000
1101100000
1111110000
1001101000
1101011100
1111111010
1011001111

Esto fue mucho más complicado de lo que esperaba ...


3

Python, 142 135 132 131 bytes

133 132 131 versión de byte

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

reemplazado r[x-1]+r[x]>1por r[x-1]&r[x]el operador bit a bit y produce el valor mínimo en(r[x-1],r[x])

¡Gracias @ThomasKwa por sugerir en n*nlugar de n**2que ahorre 1 byte!

Gracias @Shebang por el byte -1

Versión de 135 bytes

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

Gracias a @Cole por los -7 bytes:

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

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

Versión de 142 bytes

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

Ni siquiera cerca de la respuesta de @ Jakube, pero me divertí mucho codificando y jugando golf.

Espera dos entradas: la primera entrada es el número de filas y la segunda entrada es la lista de fuentes de pseudoaleatoriedad . Imprime en la consola una fila tras otra, cada una en una nueva línea.

Como ejemplo:

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]

Ahora para una breve explicación sobre cómo funciona:

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    

El truco aquí es que sabemos que la lista de bits siempre comenzará y terminará con un 1porque el primer y el último elemento nunca se modifican debido a las especificaciones. de la pregunta Esa es la razón de la declaración [1]+r+[1].

Pero si rse inicializa como [1], no hay cambios en la primera fila y luego agregamos [1]+r+[1]¿cómo es que la segunda fila no lo es [1,1,1]?

Esto se debe al hecho de que en la primera iteración i=1de modo range(1,i)devuelve una lista vacía y, como resultado de la foren la lista de la comprensión no tener nada que iterar sobre rconvierte en una lista vacía de modo [1]+r+[1]=[1,1]. ¡Esto solo sucede en la primera iteración, lo cual es ideal para nosotros!

PD: Siéntase libre de hacer sugerencias sobre cómo jugar más al golf.


1
Mis disculpas si no entiendo el desafío correctamente, pero ¿no puedes reemplazarlo min(a,b)con a+b>1y max(a,b)con a+b? Me doy cuenta de que probablemente tengas que hacer algo para manejar el primer caso de 1-> 11(creo que podrías hacerlo L=[1]+f()..., o encontrar alguna forma de insertar 1 en la parte delantera Lporque eso siempre aparecería 1 para la segunda línea)
cole

@Cole Afortunadamente, no es necesario realizar cambios en el resto del programa, ya que los cambios solo afectan la forma de conocer los valores mínimo y máximo de un par de bits.
Ioannes

1
Te perdiste que puedes eliminar un espacio aquí: r[x-1]&r[x] else:)
Kade

¿Funcionaría n ** 2 -> n * n?
lirtosiast el

@Thomas Tienes razón!
Ioannes

2

MATLAB, 146 143 138

(También funciona en Octave en línea, pero debe iniciar sesión para guardar la función en un archivo).

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

La función toma una entrada ny L, y devuelve una matriz oque contiene la salida.

Para los valores de entrada, nes un escalar y Les un vector de columna, que puede especificarse en el formato [;;;]. No es exactamente lo que muestra, pero dice que es flexible dentro de lo razonable y esto parece ser así.

La salida está formateada como una n x nmatriz que contiene 0 y 1.

Y una explicación:

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

Actualización: He logrado optimizar la declaración if-else para guardar algunos bytes. El formato de entrada ha vuelto a cambiar al vector de columna.


1

Haskell, 153 149 bytes

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

%devuelve una lista de listas de bits. Ejemplo de uso:

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

¡Oh querido! Llevar la lista al azar Les puro dolor. Veamos si esto puede ser más corto.


1

C #, 152 bytes

No hay nada especial aquí. La función devuelve una matriz 2D donde el primer rango es la línea y el segundo es la columna.

Sangrado y nuevas líneas para mayor claridad:

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 bytes

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 no tiene un operador de incremento, ¿verdad? Bueno, más o menos. La variable de ecuación u, normalmente utilizada con secuencias, tiene una característica oscura: cuando use llama con un argumento, la variable 𝑛se establece en uno mayor que ese argumento. El incremento condicional depende de esto. (He estado esperando para usarlo durante mucho tiempo).

Para que la indexación de listas funcione correctamente, 𝑛debe ser su valor predeterminado de 0, y 𝑛Mindebe ser su valor predeterminado de 1, por lo tanto, borre la RAM de su calculadora o establezca esos valores manualmente antes de ejecutar esto.

augment({0},Ans)+augment(Ans,{0calcula una lista de sumas de dos elementos adyacentes, por lo que devolverá una lista de 0s, 1s y 2s. Entonces la magia está en esta línea:

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

El resultado de esta línea será que los elementos de la lista son 0 si eran 0 o si fueran 2 y el bit leído era 0.

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

Caso de prueba:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.