Menganalisis Gempa Bumi


17

Latar Belakang

The acak Domino Automaton adalah model mainan untuk gempa bumi, terinspirasi oleh automata seluler. Dalam tantangan ini, tugas Anda adalah untuk mensimulasikan versi model ini yang disederhanakan, dan mengumpulkan data darinya.

Otomat didefinisikan pada sebuah array Adari kbit, yang mewakili garis patahan yang gempa bumi dapat terjadi. Array membungkus di sekitar perbatasannya. Kondisi itu A[i] = 0berarti posisi iitu rileks , dan itu A[i] = 1berarti ia bersemangat , atau mengandung energi yang tersimpan. Pada setiap langkah waktu, satu posisi array dipilih secara acak. Jika posisi itu rileks, ia menjadi bersemangat (energi potensial ditambahkan ke sistem). Jika posisi itu sudah bersemangat, itu memicu gempa bumi, dan posisi yang dipilih dan semua posisi bersemangat yang terhubung lagi menjadi rileks. Jumlah posisi tereksitasi yang menjadi rileks adalah besarnya gempa.

Contoh

Pertimbangkan array

100101110111

panjang 12. Jika proses acak memilih bit kedua dari kiri, array diperbarui ke

110101110111
 ^

sejak bit yang dipilih (ditandai dengan ^) adalah 0. Jika kita selanjutnya memilih bit keempat dari kiri, yang merupakan terisolasi 1, gempa berkekuatan 1 dipicu, dan bit diatur ke 0lagi:

110001110111
   ^

Selanjutnya, kita dapat memilih bit kedua dari kanan, yang memicu gempa berkekuatan 5:

000001110000
          ^

Perhatikan bahwa semua 1s dalam "cluster" yang sama dengan yang dipilih adalah bagian dari gempa, dan array membungkus di perbatasan.

Tugas

Anda harus mengambil sebagai input dua bilangan bulat positif kdan t, dan tugas Anda adalah mensimulasikan otomat domino acak untuk tlangkah-langkah waktu, mulai dari karray panjang awal semua 0s. Output akan menjadi daftar Ldari kbilangan bulat, di mana L[i](dengan pengindeksan berbasis 1) berisi jumlah gempa bumi besarnya iyang terjadi selama simulasi. Anda diizinkan untuk meninggalkan nol yang tertinggal dari output.

Untuk input k = 15dan t = 1000, beberapa output representatif adalah

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

Aturan

Program dan fungsi lengkap diizinkan. Hitungan byte terpendek menang, dan celah standar tidak diizinkan.

Perhatikan bahwa Anda tidak perlu mensimulasikan robot menggunakan implementasi tertentu, hanya masalah output.


2
Apakah mungkin Anda dapat menambahkan tanda sisipan ^ di bawah bit yang berubah? Mungkin memudahkan untuk memvisualisasikan contoh
DeadChex

1
@DeadChex Ide bagus, diperbarui.
Zgarb

Jawaban:


2

Pyth, 48 byte

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

Mendapat sedikit terinspirasi oleh penjelasan @ Dennis. Punya beberapa pemikiran serupa kemarin, tetapi tidak benar-benar mengikuti mereka.

Cobalah online: Demonstrasi

Penjelasan:

      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=}

Ini adalah fungsi anonim yang muncul k dan t dari tumpukan ( k di atas t ) dan meninggalkan array yang diinginkan sebagai imbalan.

Cobalah online di Internet juru bahasa CJam .

Bagaimana itu bekerja

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

Ternyata saya punya solusi yang hampir sama dengan Fry , tetapi dengan sedikit lebih mengutak-atik.


Wow saya benar-benar melihat randrange, tetapi saya tidak menyadari itu hanya bekerja dengan satu argumen. Kerja bagus!
FryAmTheEggman

4

Java, 278 272 byte

Java bukan bahasa Golf terbaik, dan saya bukan pegolf terbaik, tapi sangat menyenangkan untuk menulis jadi ini dia! Beri tahu saya tentang bug dan peningkatan! (Saya memutuskan untuk mengirim kembali hanya sebagai fungsi.)

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

Dan file dengan spasi dan komentar:

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
 }

Jika Anda bisa sedikit menguraikan komentar di program ke-2, itu mungkin membantu keterbacaan. Terima kasih. (Gunakan Alt+09, atau tab di Notepad ++)
mbomb007

d[q]+=1;ini bisa menjadi d[q]++;Anda dapat menambahkan langsung pada array daripada menggunakan + = di mana-mana. Itu harus menyimpan banyak karakter.
Kompas

@ Compass Sudah membuat perubahan itu, terima kasih!
DeadChex

1
Juga: for(;t>0;t--){ dapat diubah menjadi for(;t-->0;){: D
Kompas

Selamat atas golf pertama Anda di sini! : D Sekarang .... dengan hanya menata ulang deklarasi sedikit dan mengembalikan (alih-alih mencetak) hasilnya, Anda bisa mendapatkan ini sedikit. Mungkin ada lebih banyak yang harus dilakukan, tetapi saya harus pergi. Berikut ini adalah versi 244 byte: 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]

Terima kasih @Vioz untuk menemukan cara yang lebih singkat untuk membuatnya D, dan membuktikan lagi bahwa notbiasanya golfable. Dan juga untuk menulis penjelasannya.

Saya telah mencoba membuat program serupa di Pyth, tetapi tampaknya ada masalah ruang lingkup dalam apa yang saya coba lakukan. Ini secara naif mengimplementasikan kartu domino dan fungsinya Umenyebarkan gempa bumi. Arah pengurangan Utidak memerlukan mod karena akan membungkus secara alami. Elemen terakhir dariE menghitung berapa kali nol diubah menjadi satu, sehingga tidak dicetak pada akhirnya.

Tidak Tergabung + Penjelasan:

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
Mengubah D[r]=not euntuk D[r]=e<1menyimpan 2 byte, dan E=[0]*-~kuntuk E=D+[0]menyimpan 2 lainnya, untuk membuat Anda turun ke 170.
Kade

1

ES6, 224 196 189 179 172

Barang-barang yang mudah telah di-golf, tetapi masih ada beberapa pekerjaan yang harus dilakukan. Saya akan mengetikkan penjelasan nanti. Juga, jika seseorang dapat memberi tahu saya mengapa new Date%khal pendek tidak berfungsi dengan baik lagi, itu akan membengkak.

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}

Penggunaan adalah

f(10, 1000);

Anda dapat menghapus new. Anda tidak memerlukan itu tdalam for loop, Tidak perlu dua yang terakhir;
Pengoptimal

@Optimizer yang menyebabkan Anda pahlawan
Kompas

a[r]^=1akan berfungsi jika nilai awal salah satu 1atau0
Pengoptimal

1

Perl, 212

Versi sebelumnya yang saya pasang tidak benar, dan implementasinya membutuhkan beberapa pekerjaan.

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}

Ini mungkin bukan algoritma yang tepat untuk ini, tapi saya tidak bisa berpikir sekarang. Versi ungolfed di bawah.

Tidak Disatukan:

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

Ya, ini tidak terlalu kompetitif. Tapi karena butuh waktu cukup lama, saya pikir saya tetap akan mempostingnya.

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.

Cobalah online

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.