Analyse des tremblements de terre

17

Contexte

Le Random Domino Automaton est un modèle de jouet pour les tremblements de terre, inspiré des automates cellulaires. Dans ce défi, votre tâche consiste à simuler une version simplifiée de ce modèle et à en collecter des données.

L'automate est défini sur un tableau Ade kbits, représentant une ligne de faille sur laquelle des tremblements de terre peuvent se produire. Le tableau s'enroule autour de ses frontières. La condition A[i] = 0signifie que la position iest détendue et A[i] = 1signifie qu'elle est excitée ou contient de l'énergie stockée. À chaque pas de temps, une position de la matrice est choisie uniformément au hasard. Si cette position est détendue, elle devient excitée (une énergie potentielle est ajoutée au système). Si cette position est déjà excitée, elle déclenche un tremblement de terre, et la position choisie et toutes les positions excitées qui y sont reliées sont à nouveau détendues. Le nombre de positions excitées qui se relâchent est la magnitude du tremblement de terre.

Exemple

Considérez le tableau

100101110111

de longueur 12. Si le processus aléatoire choisit le deuxième bit de gauche, le tableau est mis à jour pour

110101110111
 ^

puisque le bit choisi (marqué avec ^) était 0. Si nous choisissons ensuite le quatrième bit de gauche, qui est un bit isolé 1, un tremblement de terre de magnitude 1 est déclenché et le bit est remis à 0nouveau:

110001110111
   ^

Ensuite, nous pourrions choisir le deuxième bit de droite, ce qui déclenche un tremblement de terre de magnitude 5:

000001110000
          ^

Notez que tous les 1s dans le même "cluster" que celui choisi faisaient partie du tremblement de terre, et le tableau s'enroule à la frontière.

La tâche

Vous devez prendre en entrée deux entiers positifs ket t, et votre tâche consiste à simuler l'automate domino aléatoire pour les tpas de temps, à partir d'un ktableau de longueur initial de tous les 0s. Votre sortie doit être une liste Ld' kentiers, où L[i](avec une indexation basée sur 1) contient le nombre de tremblements de terre de magnitude iqui se sont produits pendant la simulation. Vous êtes autorisé à supprimer les zéros de fin de la sortie.

Pour les entrées k = 15et t = 1000, certaines sorties représentatives sont

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

Règles

Les programmes complets et les fonctions sont autorisés. Le nombre d'octets le plus court l'emporte et les failles standard sont interdites.

Notez que vous n'êtes pas obligé de simuler l'automate à l'aide d'une implémentation particulière, seule la sortie compte.

Zgarb
la source
2
Est-il possible que vous puissiez ajouter un caret ^ sous le bit qui change? Cela pourrait faciliter la visualisation de l'exemple
DeadChex
1
@DeadChex Bonne idée, mise à jour.
Zgarb

Réponses:

2

Pyth, 48 octets

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

J'ai été un peu inspiré par l'explication de @ Dennis. J'ai eu des pensées similaires hier, mais je ne les ai pas vraiment suivies.

Essayez-le en ligne: Démonstration

Explication:

      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
Jakube
la source
5

CJam, 57 55 octets

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

Il s'agit d'une fonction anonyme qui extrait k et t de la pile ( k en haut de t ) et laisse le tableau souhaité en retour.

Essayez-le en ligne dans l' interpréteur CJam .

Comment ça fonctionne

: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.
Dennis
la source
4

Python 2, 153 octets

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

Il s'avère que j'avais presque la même solution que Fry's , mais avec un peu plus de tripotage.

Sp3000
la source
Wow, j'avais réellement regardé randrange, mais je ne savais pas que cela fonctionnait avec un seul argument. Bon travail!
FryAmTheEggman
4

Java, 278 272 octets

Java n'est pas le meilleur langage de golf, et je ne suis pas le meilleur golfeur, mais c'était très amusant d'écrire alors le voici! Faites-moi part des bugs et des améliorations! (J'ai décidé de soumettre à nouveau comme une simple fonction.)

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

Et le fichier avec des espaces et des commentaires:

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
 }
DeadChex
la source
Si vous pouviez tabuler un peu les commentaires dans le 2ème programme, cela pourrait aider à la lisibilité. Merci. (Utilisez Alt+09-le ou
notez-le
d[q]+=1;cela peut devenir d[q]++;vous pouvez incrémenter directement sur les tableaux au lieu d'utiliser + = partout. Cela devrait sauver un tas de personnages.
Compass
@Compass Vous avez déjà fait ce changement, merci cependant!
DeadChex
1
Aussi: for(;t>0;t--){ peut être changé en for(;t-->0;){: D
Compass
Félicitations pour votre premier golf ici! : D Maintenant .... en réarrangeant juste un peu les déclarations et en retournant (au lieu d'imprimer) le résultat, vous pouvez obtenir cela un peu. Il y a peut-être plus à faire, mais je dois y aller. Voici une version de 244 octets: pastebin.com/TWAXvyHW
Geobits
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]

Merci à @Vioz d'avoir trouvé un moyen plus court de faire D et de prouver à nouveau que notc'est généralement golfable. Et aussi pour avoir écrit l'explication.

J'avais essayé de créer un programme similaire en Pyth, mais il semble y avoir un problème de portée dans ce que j'essayais de faire. Cela implémente assez naïvement les dominos et la fonction Upropage les tremblements de terre. La direction de soustraction dans Un'a pas besoin d'un mod car elle s'enroulera naturellement. Le dernier élément deE compte le nombre de fois où un zéro est transformé en un, il n'est donc pas imprimé à la fin.

Non golfé + Explication:

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
FryAmTheEggman
la source
1
Passer D[r]=not een D[r]=e<1sauvegarde 2 octets, et E=[0]*-~ken E=D+[0]sauvegarder 2 autres, pour vous ramener à 170.
Kade
1

ES6, 224 196 189 179 172 172

Les choses faciles ont été jouées au golf, mais il reste encore du travail à faire. Je vais taper une explication plus tard. Aussi, si quelqu'un peut me dire pourquoi le courtnew Date%k ne fonctionne plus si bien, ce serait bien.

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'utilisation est

f(10, 1000);
Boussole
la source
Vous pouvez supprimer le fichier new. Vous n'avez pas besoin de cela tdans la boucle for, pas besoin de ces deux derniers;
Optimizer
@Optimizer vous êtes un héros à provoquer
Compass
a[r]^=1fonctionnera si la valeur initiale est 1ou0
Optimizer
1

Perl, 212

La version précédente que j'avais mise en place n'était pas correctement encapsulée, et la mise en œuvre a demandé un certain travail.

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}

Ce n'est probablement pas le bon algorithme pour cela, mais je ne peux pas penser en ce moment. La version non golfée est ci-dessous.

Non golfé:

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";
jja
la source
1

CJam, 76 octets

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

Eh bien, ce n'est pas très compétitif. Mais comme cela m'a pris assez de temps, j'ai pensé que je le publierais de toute façon.

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.

Essayez-le en ligne

Reto Koradi
la source