Erdbeben analysieren


17

Hintergrund

Der Random Domino Automaton ist ein Spielzeugmodell für Erdbeben, das von zellularen Automaten inspiriert wurde. In dieser Herausforderung besteht Ihre Aufgabe darin, eine vereinfachte Version dieses Modells zu simulieren und Daten daraus zu sammeln.

Der Automat ist auf einer Reihe Avon kBits definiert, die eine Fehlerlinie darstellen, auf der Erdbeben auftreten können. Das Array wird an den Rändern herumgewickelt. Die Bedingung A[i] = 0bedeutet , dass Position iist entspannt , und A[i] = 1bedeutet , dass es erregt , oder enthält Energie gespeichert. Zu jedem Zeitschritt wird eine Position des Arrays gleichmäßig zufällig ausgewählt. Wenn diese Position entspannt ist, wird sie angeregt (dem System wird potentielle Energie hinzugefügt). Wenn diese Position bereits angeregt ist, wird ein Erdbeben ausgelöst, und die ausgewählte Position und alle damit verbundenen angeregten Positionen werden wieder entspannt. Die Anzahl der angeregten Positionen, die sich entspannen, ist die Stärke des Erdbebens.

Beispiel

Betrachten Sie das Array

100101110111

der Länge 12. Wenn der Zufallsprozess das zweite Bit von links auswählt, wird das Array auf aktualisiert

110101110111
 ^

da das gewählte bit (markiert mit ^) war 0. Wenn wir als nächstes das vierte Bit von links auswählen, das ein isoliertes 1Bit ist, wird ein Ohrbeben der Stärke 1 ausgelöst und das Bit 0erneut auf gesetzt:

110001110111
   ^

Als nächstes können wir das zweite Bit von rechts auswählen, das ein Erdbeben der Stärke 5 auslöst:

000001110000
          ^

Beachten Sie, dass alle 1s in demselben "Cluster" wie der ausgewählte Teil des Bebens waren und das Array an der Grenze herumläuft.

Die Aufgabe

Als Eingabe nehmen Sie zwei positive ganze Zahlen kund t, und Ihre Aufgabe ist es, den zufälligen tDominoautomaten kfür Zeitschritte zu simulieren , ausgehend von einem anfänglichen Längenarray aller 0s. Ihre Ausgabe soll eine Liste Lvon kganzen Zahlen sein, wobei L[i](mit 1-basierter Indizierung) die Anzahl der Erdbeben der Stärke enthält i, die während der Simulation aufgetreten sind. Sie dürfen nachgestellte Nullen aus der Ausgabe entfernen.

Für die Eingänge k = 15und t = 1000sind einige repräsentative Ausgänge

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

Regeln

Es sind sowohl vollständige Programme als auch Funktionen zulässig. Die kürzeste Byteanzahl gewinnt, und Standardlücken sind nicht zulässig.

Beachten Sie, dass Sie den Automaten nicht mit einer bestimmten Implementierung simulieren müssen, sondern nur die Ausgabe.


2
Ist es möglich, dass Sie unter dem Bit, das sich ändert, ein Caret ^ einfügen können?
Dies

1
@DeadChex Gute Idee, aktualisiert.
Zgarb

Antworten:


2

Pyth, 48 Bytes

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

Habe mich ein bisschen von @ Dennis 'Erklärung inspirieren lassen. Hatte gestern einige ähnliche Gedanken, folgte ihnen aber nicht wirklich.

Probieren Sie es online aus: Demonstration

Erläuterung:

      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 Bytes

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

Dies ist eine anonyme Funktion, die k und t vom Stapel ( k über t ) abruft und das gewünschte Array zurücklässt.

Probieren Sie es online im CJam-Interpreter aus .

Wie es funktioniert

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

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

Es stellte sich heraus, dass ich fast die gleiche Lösung hatte wie Fry's , aber mit ein bisschen mehr Fummelei.


Wow, ich hatte es mir tatsächlich angeschaut randrange, aber mir war nicht klar, dass es nur mit einem Argument funktionierte. Gute Arbeit!
FryAmTheEggman

4

Java, 278 272 Bytes

Java ist nicht die beste Golfsprache und ich bin nicht der beste Golfer, aber es hat sehr viel Spaß gemacht zu schreiben, also ist es hier! Informieren Sie mich über Bugs und Verbesserungen! (Ich habe mich entschieden, es nur als Funktion erneut einzureichen.)

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

Und die Datei mit Leerzeichen und Kommentaren:

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
 }

Wenn Sie die Kommentare im 2. Programm ein wenig streichen könnten, könnte dies die Lesbarkeit verbessern. Vielen Dank. (Benutze Alt+09oder tabuliere es in Notepad ++)
mbomb007

d[q]+=1;Dies kann dazu führen, dass d[q]++;Sie direkt auf Arrays inkrementieren können, anstatt überall + = zu verwenden. Das sollte eine Menge Zeichen sparen.
Kompass

@Compass Diese Änderung wurde bereits vorgenommen, aber danke!
DeadChex

1
Außerdem: for(;t>0;t--){ kann geändert werden in for(;t-->0;){: D
Kompass

Herzlichen Glückwunsch zu Ihrem ersten Golf hier! : D Nun .... indem Sie einfach die Deklarationen ein wenig umstellen und das Ergebnis zurückgeben (anstatt es zu drucken), können Sie dies ziemlich viel runterholen. Möglicherweise muss noch mehr getan werden, aber ich muss gehen. Hier ist eine 244 - Byte - Version: 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]

Vielen Dank an @Vioz, dass Sie einen kürzeren Weg gefunden haben D, und erneut bewiesen haben, dass notdas normalerweise golfen kann. Und auch zum Schreiben der Erklärung.

Ich hatte versucht, ein ähnliches Programm in Pyth zu erstellen, aber es scheint ein Problem mit dem Umfang meiner Versuche zu geben. Das setzt die Dominosteine ​​ziemlich naiv um und die Funktion Uverbreitet Erdbeben. Die Subtraktionsrichtung in Ubenötigt keinen Mod, da sie sich auf natürliche Weise ändert. Das letzte Element von Ezählt, wie oft aus einer Null eine Eins wird, sodass es am Ende nicht gedruckt wird.

Ungolfed + Erklärung:

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
Ändern, D[r]=not eum D[r]=e<12 Bytes zu speichern, und E=[0]*-~kum E=D+[0]weitere 2 zu speichern, um Sie auf 170 zu bringen.
Kade

1

ES6, 224 196 189 179 172

Das einfache Zeug wurde gespielt, aber es gibt noch einiges zu tun. Ich schreibe später eine Erklärung aus. Auch wenn mir jemand sagen kann, warum das kurze new Date%kDing nicht mehr so ​​gut funktioniert, wäre das großartig.

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}

Verwendung ist

f(10, 1000);

Sie können das entfernen new. Das brauchst du nicht tin der for-Schleife, die letzten beiden brauchst du nicht;
Optimizer

@Optimizer Sie sind Held zu verursachen
Compass

a[r]^=1wird defs funktionieren, wenn der anfängliche Wert entweder 1oder ist0
Optimierer

1

Perl, 212

Die vorherige Version, die ich erstellt hatte, war nicht korrekt verpackt, und die Implementierung nahm einige Arbeit in Anspruch.

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}

Dies ist wahrscheinlich nicht der richtige Algorithmus dafür, aber ich kann im Moment nicht denken. Die ungolfed Version ist unten.

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 Bytes

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

Nun, das ist nicht sehr wettbewerbsfähig. Aber da ich lange genug gebraucht habe, dachte ich, ich würde es trotzdem posten.

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.

Probieren Sie es online aus

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.