Automa cellulare pseudocasuale


14

introduzione

In questa sfida, simuleremo un certo automa cellulare probabilistico usando numeri pseudocasuali pessimi. L'automa cellulare è definito su stringhe binarie dalla seguente regola locale. Supponiamo che il vicino di sinistra di una cella e la cella stessa abbiano stati ae b.

  • Se min(a,b) == 0, allora il nuovo stato di bè max(a,b).
  • Se min(a,b) == 1, allora il nuovo stato di bviene scelto casualmente da {0,1}.

La seguente immagine mostra una possibile evoluzione in 10 passaggi di un singolo 1.

1
11
101
1111
11001
101011
1111111
10001001
110011011
1010111101

Nota come a 1volte due s adiacenti si evolvono in 1, e talvolta in 0, e i bit più bordi sono sempre 1s. Il tuo compito è quello di produrre un'evoluzione automa cellulare di questa forma.

ingressi

I tuoi input sono un numero intero positivo n, che indica il numero di righe da visualizzare e un elenco non vuoto di bit L, che utilizziamo come fonte di casualità.

Produzione

L'output è un elenco di elenchi o array 2D di bit, che rappresentano l'evoluzione di un singolo 1per i npassi temporali, come nella figura sopra. 0Se lo si desidera, è possibile riempire l'output di s per ottenere file di uguale lunghezza, ma non devono essere presenti 0s iniziali .

Le scelte casuali nell'automa cellulare devono essere disegnate dall'elenco L, tornando all'inizio quando è esaurito. Più esplicitamente, se l'output viene attraversato una riga alla volta dall'alto verso il basso, da sinistra a destra, le scelte casuali successive formano l'elenco Lripetuto tutte le volte necessarie.

Esempio

Supponiamo che gli input siano n = 7e L = [0,1,0]. Quindi l'automa cellulare si evolve come segue durante i 7 passaggi, dove abbiamo posto un vdiritto sopra ogni scelta casuale:

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

Se leggiamo tutti i bit contrassegnati con a v, otteniamo 01001001, che viene Lripetuto 2,66 volte. Il prossimo bit casuale sarebbe 0.

Regole e punteggio

È possibile scrivere un programma completo o una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard. Il formato esatto degli ingressi e delle uscite non è importante (entro limiti ragionevoli).

Casi test

Versione deterministica, ogni bit casuale è 0:

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

Ogni bit casuale è 1:

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

Versioni pseudocasuali:

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

Risposte:


3

Pyth, 33 byte

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

Provalo online: dimostrazione o Test Suite

Spiegazione:

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 byte

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

Dove <empty>indica che esiste una riga vuota finale. Ogni riga va in un file separato e il# deve essere sostituita con linefeed (0x0A).

Si aspetta che l'input sia nin unario (fatto di zero, come in Unario ), seguito da uno spazio, seguito dalla stringa "pseudo-casuale", ad es. 10, [1, 0, 0, 1]Verrebbe letto come

0000000000 1001

L'output è come nella sfida, ma riempito di zero, ad es

1000000000
1100000000
1110000000
1001000000
1101100000
1111110000
1001101000
1101011100
1111111010
1011001111

Questo è stato molto più complicato di quanto mi aspettassi ...


3

Python, 142 135 132 131 byte

133 132 versione 131 131 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

sostituito r[x-1]+r[x]>1da r[x-1]&r[x]erano l'operatore bit per bit e restituisce il valore minimo in(r[x-1],r[x])

Grazie @ThomasKwa per aver suggerito n*ninvece di n**2quale salva 1 byte!

Grazie @Shebang per il -1 byte

Versione da 135 byte

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

Grazie a @Cole per i -7 byte:

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

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

Versione da 142 byte

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

Nemmeno vicino alla risposta di @ Jakube ma mi sono divertito molto a scrivere codice e giocare a golf.

Prevede due input: il primo input è il numero di righe e il secondo input è l' elenco delle fonti di pseudo casualità . Stampa su console una riga dopo l'altra, ognuna su una nuova riga.

Come esempio:

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]

Ora per una breve spiegazione su come funziona:

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    

Il trucco qui è che sappiamo che l'elenco dei bit inizierà e finirà sempre con un 1perché il primo e l'ultimo elemento non vengono mai modificati a causa delle specifiche. della domanda. Questa è la ragione per l'affermazione [1]+r+[1].

Ma se rè inizializzato come [1], non ci sono cambiamenti nella prima riga e quindi aggiungiamo [1]+r+[1]come mai la seconda riga non lo è [1,1,1]?

Ciò è dovuto al fatto che alla prima iterazione restituisce i=1così range(1,i)un elenco vuoto e, come risultato della forcomprensione nell'elenco, non avere nulla su cui iterare rdiventa un elenco vuoto [1]+r+[1]=[1,1]. Questo accade solo alla prima iterazione che è semplicemente l'ideale per noi!

PS: sentiti libero di dare qualche suggerimento su come giocare a golf di più.


1
Mi scuso se non capisco correttamente la sfida, ma non puoi sostituirla min(a,b)con a+b>1e max(a,b)con a+b? Mi rendo conto che probabilmente dovresti fare qualcosa per gestire il primo caso di 1-> 11(penso che potresti fare L=[1]+f()..., o trovare un modo per inserire 1 nella parte anteriore Lperché ciò farebbe sempre apparire 1 per la seconda riga)
cole

@Cole Fortunatamente non è necessario apportare modifiche al resto del programma poiché le modifiche influiscono solo sul modo di conoscere i valori minimo e massimo di una coppia di bit.
Ioannes,

1
Ti sei perso che puoi rimuovere uno spazio qui: r[x-1]&r[x] else:)
Kade,

N ** 2 -> n * n funzionerebbe?
lirtosiast,

@Thomas Hai ragione!
Ioannes,

2

MATLAB, 146 143 138

(Funziona anche su Octave online, ma è necessario accedere per salvare la funzione in un file).

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 funzione accetta un input ne Lrestituisce un array oche contiene l'output.

Per i valori di input, n è uno scalare ed Lè un vettore di colonna, che può essere specificato nel formato [;;;]. Non proprio quello che mostri, ma dici che è flessibile all'interno della ragione e questo sembra così.

L'output è formattato come un n x narray contenente 0 e 1.

E una spiegazione:

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

Aggiornamento: sono riuscito a ottimizzare l'istruzione if-else per salvare alcuni byte. Il formato di input è tornato nuovamente al vettore colonna.


1

Haskell, 153 149 byte

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

%restituisce un elenco di elenchi di bit. Esempio di utilizzo:

> 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 caro! Portare la lista casuale in Lgiro è puro dolore. Vediamo se questo può essere più breve.


1

C #, 152 byte

Non c'è niente di speciale qui. La funzione restituisce un array 2D in cui il primo rango è la linea e il secondo è la colonna.

Linee rientrate e nuove per chiarezza:

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 byte

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 non ha un operatore di incremento, giusto? Bene, in qualche modo. La variabile di equazione u, normalmente utilizzata con le sequenze, ha una caratteristica oscura: quando uviene chiamata con un argomento, la variabile𝑛 viene impostata su una maggiore di tale argomento. L'incremento condizionale dipende da questo. (Sto aspettando di usarlo da molto tempo.)

Perché l'indicizzazione degli elenchi funzioni correttamente, 𝑛deve essere il valore predefinito 0 e 𝑛Mindeve essere il valore predefinito 1, quindi cancellare la RAM della calcolatrice o impostare tali valori manualmente prima di eseguirlo.

augment({0},Ans)+augment(Ans,{0calcola un elenco di somme di due elementi adiacenti, quindi restituirà un elenco di 0, 1 e 2 secondi. Quindi la magia è su questa linea:

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

Il risultato di questa riga sarà che gli elementi dell'elenco sono 0 se fossero 0 o se fossero 2 e il bit letto fosse 0.

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

Caso di prova:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.