Analizzare i terremoti


17

sfondo

Il Random Domino Automaton è un modello giocattolo per i terremoti, ispirato agli automi cellulari. In questa sfida, il tuo compito è simulare una versione semplificata di questo modello e raccoglierne i dati.

L'automa è definito su una matrice Adi kbit, che rappresenta una linea di faglia su cui possono verificarsi terremoti. L'array si avvolge ai suoi bordi. La condizione A[i] = 0significa che la posizione iè rilassata e A[i] = 1significa che è eccitata o contiene energia immagazzinata. Ad ogni fase, una posizione dell'array viene scelta in modo uniforme a caso. Se quella posizione viene rilassata, diventa eccitata (l'energia potenziale viene aggiunta al sistema). Se quella posizione è già eccitata, si innesca un terremoto e la posizione scelta e tutte le posizioni eccitate ad essa collegate vengono nuovamente rilassate. Il numero di posizioni eccitate che si rilassano è l' entità del terremoto.

Esempio

Considera l'array

100101110111

di lunghezza 12. Se il processo casuale sceglie il secondo bit da sinistra, l'array viene aggiornato

110101110111
 ^

poiché il bit scelto (contrassegnato con ^) era 0. Se scegliamo successivamente il quarto bit da sinistra, che è un isolato 1, viene attivato un terremoto di magnitudo 1 e il bit viene 0nuovamente impostato su :

110001110111
   ^

Successivamente, potremmo scegliere il secondo bit da destra, che innesca un terremoto di magnitudo 5:

000001110000
          ^

Si noti che tutti gli 1s nello stesso "cluster" di quello scelto facevano parte del sisma e l'array si avvolge attorno al bordo.

L'obiettivo

Si deve prendere come input due interi positivi ke t, e il vostro compito è quello di simulare l'automa domino casuale per tpassi temporali, a partire da un length- primo karray di tutti 0s. L'output deve essere un elenco Ldi knumeri interi, dove L[i](con indicizzazione basata su 1) contiene il numero di terremoti di magnitudo iverificatisi durante la simulazione. È consentito eliminare gli zero finali dall'output.

Per gli input k = 15e t = 1000, alcuni output rappresentativi sono

[117, 97, 45, 26, 10, 5, 3, 1, 3, 0, 0, 0, 0, 0, 0]
[135, 91, 58, 21, 8, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0]
[142, 63, 51, 31, 17, 4, 2, 1, 1, 0, 0, 0, 0, 0, 0]
[106, 75, 45, 30, 16, 8, 5, 2, 2, 0, 0, 0, 0, 0, 0]
[111, 96, 61, 22, 3, 8, 3, 2, 0, 0, 0, 1, 0, 0, 0]

Regole

Sono ammessi programmi e funzioni completi. Vince il conteggio dei byte più breve e non sono consentite scappatoie standard.

Si noti che non è necessario simulare l'automa utilizzando un'implementazione particolare, solo l'output è importante.


2
È possibile aggiungere un punto di inserimento ^ sotto il bit che cambia? Potrebbe semplificare la visualizzazione dell'esempio
DeadChex,

1
@DeadChex Buona idea, aggiornata.
Zgarb,

Risposte:


2

Pyth, 48 byte

Km0QJsM.u?<+vM.sjkZ\1KQe=Z.>NOQ+PZ1vwKm/-VJtJhdQ

Mi sono ispirato un po 'alla spiegazione di @Dennis. Ieri ha avuto pensieri simili, ma non li ha davvero seguiti.

Provalo online: dimostrazione

Spiegazione:

      implicit: Q is the first input number
 m0Q  create a list with Q zeros
K     store the list in K


       .u                      vwK   apply the following expression eval(input) times, 
                                     start with N = K:
                      .>NOQ            shift N by a random integer of [0, ..., Q-1]
                    =Z                 store the result in Z
     ?             e Z                 if the last digit == 1:
            jkZ                          convert Z to string
          .s   \1                        remove "1"s from the start and end
        vM                               convert to list of integers
       +         K                       add K (adds a bunch of zeros)
      <           Q                      correct size (take the first Q elements)
                                         implicitly update N with this result
                                       else:
                           PZ            all but last of Z
                          +  1           append 1
                                         implicitly update N with this result

   .u                                gives all the intermediate states
 sM                                  sum each list
J                                    store in J


m/-VJtJhdQ
m        Q   map each d in [0, 1, ..., Q-1] to:
  -VJtJ        vectorized minus between J and J[1:]
 /     hd      count d+1 in ^
             implicitly print

5

CJam, 57 55 byte

{:K,K0a*@[{Kmrm<){_{_0#>W%K0e]}2*_)}1?+}*;]1fb2/::-fe=}

Questa è una funzione anonima che apre k e t dalla pila ( k in cima t ) e la matrice foglie desiderata in cambio.

Provalo online nell'interprete CJam .

Come funziona

:K         e# Save the topmost integer (k) in K.
,          e# Push I := [0 ... K-1].
K0a*       e# Push J := [0 ... 0] (K elements).
@          e# Rotate the other integer (t) on top of the stack.
[{         e# Do t times:
  Kmr      e#   Pseudo-randomly select an integer between 0 and t-1.
  m<       e#   Rotate the array J than many units to the left.
  )        e#   Pop out the last element.
  {        e#   If it is 1:
    _      e#     Copy J.
    {      e#     Do 2 times:
      _0#  e#       Push the first index of 0 in J.
      >    e#       Discard the preceding elements.
      W%   e#       Reverse the array.
      K0e] e#       Pad it with zeroes to length K.
    }2*    e#
    _)     e#     Copy J and pop out the last element.
  }        e#
  1?       e#   Else: Push 1.
  +        e#   Push the integer on the stack on J.
}*         e#
;          e# Discard the last value of J.
]          e# Collect the intermediate values of J in an array.
1fb        e# Replace each array by the sum of its elements (number of ones).
2/         e# Split the array into chunks of length 2.
::-        e# Replace each chunk by the difference of its elements.
fe=        e# Count the occurrences of each integer in I.

4

Python 2, 153 byte

from random import*
k,t=input()
E=[0]*k
L=E+[0]
def g(i,x=0):y=E[i];E[i]=y&x^x;return y and-~g(i-1)+g(-~i%k)
exec"L[g(randrange(k),1)]+=1;"*t
print L[1:]

Ho scoperto che avevo quasi la stessa soluzione di Fry , ma con un po 'più di confusione.


Wow, in realtà l'avevo guardato randrange, ma non mi ero reso conto che funzionasse con un solo argomento. Bel lavoro!
FryAmTheEggman,

4

Java, 278 272 byte

Java non è il miglior linguaggio del golf, e io non sono il miglior golfista, ma è stato molto divertente scrivere, quindi eccolo qui! Fammi sapere su bug e miglioramenti! (Ho deciso di inviare nuovamente come una funzione.)

void e(int k, int t){int[]d=new int[k],b=d.clone();for(;t-->0;){int m=0,q=(int)(Math.random()*k),i=q,h=1,f=0;d[q]++;if(d[q]>1){for(;;){if(i<0){i=k-1;h=-1;}if(d[i%k]>0){m++;d[i%k]=0;}else{if(f>0)break;h*=-1;i=q;f=1;}i+=h;}b[m-1]++;}}System.out.println(Arrays.toString(b));}

E il file con spazi e commenti:

void e(int k, int t){
    int[]d=new int[k],b=d.clone();          //b is the record, d is the map   

    for(;t-->0;){                           //do time steps //q is the spot
      int m=0,q=(int)(Math.random()*k),i=q,h=1,f=0; 
                        //m-magnitude,i spot examining, h moving index, f change counter
      d[q]++;                               //add the energy
      if(d[q]>1){                           //double energy, quake here 
        for(;;){                            //shorthand while true
          if(i<0){                          //i has wrapped negative, need to start a left hand search from the end now
            i=k-1;                          //Start at the end
            h=-1;                           //Left handed search
          }
          if(d[i%k]>0){                     //is the spot energetic and set off
           m++;                             //add one to the mag counter
           d[i%k]=0;                        //remove energy
          } else {                          //it's a non active spot so we need to flip search direction
           if(f>0) break;                   //we've already flipped once, break
           h*=-1;                           //flip the direction now
           i=q;                             //reset the spot we look at to the epicenter
           f=1;                             //add one to the flip counter
          }
          i+=h;                             //add the search increment to the spot we look at
        }
        b[m-1]++;                           //update the mag record
      }
    }
    System.out.println(Arrays.toString(b)); //print it out
 }

Se potessi inserire un po 'i commenti nel secondo programma, ciò potrebbe aiutare con la leggibilità. Grazie. (Utilizzare Alt+09o tab in Notepad ++)
mbomb007

d[q]+=1;questo può diventare d[q]++;possibile incrementare direttamente sugli array invece di usare + = ovunque. Ciò dovrebbe salvare un sacco di personaggi.
Bussola,

@Compass Ho già apportato questa modifica, grazie comunque!
DeadChex,

1
Inoltre: for(;t>0;t--){ può essere modificato in for(;t-->0;){: D
Bussola il

Congratulazioni per il tuo primo golf qui! : D Ora .... semplicemente riordinando un po 'le dichiarazioni e restituendo (invece di stampare) il risultato, puoi farlo un bel po'. Potrebbe esserci altro da fare, ma devo andare. Ecco una versione da 244 byte: pastebin.com/TWAXvyHW
Geobits il

4

Python 2, 174 170

from random import*
k,t=input()
D=[0]*k
E=D+[0]
def U(x):b=D[x];D[x]=0;return b and-~U(x-1)+U(-~x%k)
for x in[0]*t:r=randint(0,k-1);e=U(r);E[e-1]+=1;D[r]=e<1
print E[:-1]

Grazie @Vioz per aver trovato un modo più breve di fare De aver dimostrato di nuovo che notè solitamente giocabile a golf. E anche per aver scritto la spiegazione.

Avevo provato a creare un programma simile in Pyth, ma sembra esserci un problema di portata in quello che stavo cercando di fare. Questo implementa abbastanza ingenuamente i domino e la funzione Upropaga i terremoti. La direzione di sottrazione Unon ha bisogno di una mod perché si avvolgerà naturalmente. L'ultimo elemento di Econta il numero di volte in cui uno zero viene trasformato in uno, quindi non viene stampato alla fine.

Ungolfed + Spiegazione:

from random import*
k,t=input()                            # Takes input in form k,t
D = [0]*k                              # Empty array of size k is made for
                                       # performing the simulation.
E = D+[0]                              # Empty array of size k+1 is made for
                                       # storing the magnitudes.
def U(x):                              # Define a function U that takes an int x
    b = D[x]                           # Assign b to the value at x in D
    D[x] = 0                           # Clear the value at x in D
    return b and U(x-1)+1 + U((x+1)%k) # Return the sum of U(x-1)+1 and U((x+1)%k)
                                       # if b is a 1.
for x in[0]*t:                         # Perform t tests
    r=randint(0,k-1)                   # Generate a random number between 0 and k-1
    e=U(r)                             # Assign e to the value of U(r)
    E[e-1]+=1;                         # Increment the magnitude array at position
                                       # e-1
    D[r] = e<1                         # Set D[r] to be 1 if no earthquake happened.
print E[:-1]                           # Print the magnitude list

1
Passare D[r]=not ea D[r]=e<1salvare 2 byte e E=[0]*-~ka E=D+[0]salvarne altri 2, per portarti a 170.
Kade,

1

ES6, 224 196 189 179 172

Le cose facili sono state giocate a golf, ma c'è ancora del lavoro da fare. Scriverò una spiegazione più tardi. Inoltre, se qualcuno può dirmi perché la new Date%kcosa breve non funziona più così bene, sarebbe bello.

f=(k,t)=>{a=Array(k).fill(0);o=a.slice(0);for(;t--;){c=0;r=Math.random()*k|0;if(a[r]){for(d=r+1;d<k&a[d];c++)a[d++]--;for(d=r-1;d&a[d];c++)a[d--]--;o[c]++};a[r]^=1}return o}

L'uso è

f(10, 1000);

È possibile rimuovere il new. Non ne hai bisogno tnel ciclo for, Non c'è bisogno degli ultimi due;
Optimizer,

@Optimizer sei un eroe da causare
Bussola,

a[r]^=1funzionerà sicuramente se il valore iniziale è o 1o0
Ottimizzatore il

1

Perl, 212

La versione precedente che avevo installato non si svolgeva correttamente e l'implementazione richiedeva un po 'di lavoro.

sub f{sub n{$i=($i+$d)%($#a+1)}($k,$t)=@_;@L=@a=(0)x$k;for(1..$t){$i=$x=int rand($k);if(++$a[$x]>1){$d=1;my%z;for(;;){$z{$i}=1;n;if(!$a[$i]){$d*=-1;n}last if($d>0&&$i==$x)}@z=keys %z;@a[@z]=(0)x@z;++$L[$#z]}}@L}

Questo probabilmente non è l'algoritmo giusto per questo, ma non riesco a pensare in questo momento. La versione ungolf è sotto.

Ungolfed:

sub f {
  # n() implements the iterator, so that each time it is called a
  # global index is incremented or decremented correctly wrapping
  # around
  sub n { $i = ($i + $d) % ($#a + 1) }
  # Receive input
  ($k, $t) = @_;
  # Initialise the array for earthquake magnitudes an the fault
  # line
  @L = @a = (0) x $k;

  for(1..$t){
    # Assign a random integer value to two control variables
    # $i is used for moving along the fault, and $x to remember
    # the initial value
    $i = $x = int rand($k);
    # The corresponding value in the fault line is incremented,
    # and earthquakes detected
    if(++$a[$x]>1){
      # Earthquake!
      # To propagate the earthquake, we move along the fault 
      # bouncing on unactivated nodes. We stop when we've covered
      # the entire activated block.

      # $d tracks the direction (initially forward);
      $d = 1;
      # %z keeps the indeces of known activated nodes
      my %z;

      for(;;){
        $z{$i} = 1;              # Read current node
        n;                       # Move head
        if (!$a[$i]) {           # If next one is deactivated
          $d *= -1;              # change direction
          n                      # and move the head (bounce!)
        }
        # If we've reached the beginning, and we're moving
        # forward we've covered the entire activated block
        last if ($d > 0 && $i == $x);
      }

      # Deactivate all consecutive activated nodes
      @z = keys %z;
      @a[@z] = (0) x @z;
      # And store the magnitude of the earthquake
      ++$L[$#z];
    }
  }
  # Return list of magnitudes
  @L
}

print join ' ', f(15, 1000), "\n";

1

CJam, 76 byte

l~_0a*:R@{1$mr_2$={W@@[W1]{{_@0t@)\@K+_2$=}g2$+)}fK;\(_R=)R\t:R;}{1t}?}*;;Rp

Bene, questo non è molto competitivo. Ma dal momento che mi ci è voluto abbastanza tempo, ho pensato di pubblicarlo comunque.

l~     Get input.
_0a*   Initial bit pattern, list of k zeros.
:R     Save away the list of zeros, will be used for histogram.
@{     Pull number of tries to top of stack, and start main loop.
1$mr   Generate random position in range 0 to k-1.
_2$    Duplicate current pattern and position.
=      Get current value of bit at position.
{      Start if statement. This is the block for bit value 1.
W@@    Create initial count of 1 bits in quake, and push it down the stack.
[W1]{  Start for loop over value [-1 1], the two increments for going left/right.
{      Start while loop that proceeds as long as 1 bits are found.
_@0t   Set current value of bit to 0.
@)     Get current bit counter to top of stack, and increment it.
\@     Pull list and bit position back to top of stack.
K+     Increment/decrement bit position.
_2$=   Get value at new bit position.
}g     End of while loop over 1 bits.
2$+)   Restore position to get ready to move in opposite direction.
}fK    End for loop over left/right increment.
;\(_   Pull counter of 1 bits in quake to top of stack.
R=     Get current value in histogram,
)      increment it,
R\t:R  and store it back in the histogram.
;}     End of if branch for 1 bit.
{1t}?  Else branch of if. For 0 bit, simply set it.
}*     End main loop.
;;Rp   Clean up stack and print histogram.

Provalo online

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.