地震の分析


17

バックグラウンド

ランダムドミノオートマトンは、セルオートマトンに触発された地震のためのおもちゃのモデル、です。この課題におけるタスクは、このモデルの単純化されたバージョンをシミュレートし、そこからデータを収集することです。

オートマトンはビット配列Aで定義され、k地震が発生する可能性のある断層線を表します。配列は境界で折り返されます。状態とA[i] = 0は、位置iリラックスしていること、および興奮しA[i] = 1ていること、またはエネルギーが蓄積されていることを意味します。各タイムステップで、配列の1つの位置がランダムに均一に選択されます。その位置が緩和されると、興奮します(潜在的なエネルギーがシステムに追加されます)。その位置がすでに興奮している場合、それは地震を引き起こし、選択された位置とそれに接続されているすべての興奮した位置は再びリラックスします。リラックスする興奮した位置の数は、地震の大きさです。

配列を考える

100101110111

ランダムプロセスが左から2番目のビットを選択した場合、配列は次のように更新されます。

110101110111
 ^

(でマークされた選択ビットは、以降^)でした0。次に、左から4番目のビット(分離1)を選択すると、マグニチュード1の地震がトリガーされ、ビットが0再び設定されます。

110001110111
   ^

次に、右から2番目のビットを選択すると、マグニチュード5の地震がトリガーされます。

000001110000
          ^

1選択されたものと同じ「クラスター」内のすべてのsは地震の一部であり、配列は境界で折り返されていることに注意してください。

タスク

入力として2つの正の整数kとを取りt、タスクはすべてのsのt初期の長さのk配列から開始して、タイムステップのランダムドミノオートマトンをシミュレートすることです0。出力は整数のリストLkあり、L[i](1から始まるインデックス付けで)マグニチュードの地震の数が含まれますiシミュレーション中に発生したます。出力から末尾のゼロを削除できます。

入力k = 15およびについてt = 1000、いくつかの代表的な出力は

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

ルール

完全なプログラムと機能の両方が許可されます。最短のバイトカウントが優先され、標準の抜け穴は許可されません。

特定の実装を使用してオートマトンをシミュレートする必要はなく、出力のみが重要であることに注意してください。


2
変化するビットの下にキャレット^を追加できる可能性はありますか?例の視覚化が容易になる可能性があります
-DeadChex

1
@DeadChex良いアイデア、更新。
ズガルブ

回答:


2

Pyth、48バイト

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

@Dennisの説明に少し触発されました。昨日、似たような考えがありましたが、実際にはそれらに従いませんでした。

オンラインで試す:デモンストレーション

説明:

      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バイト

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

これは、スタックからktをポップし(tの上のk)、代わりに目的の配列を残す匿名関数です。

CJamインタープリターでオンラインで試してください。

使い方

: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バイト

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

Fryとほぼ同じ解決策がありましたが、もう少し手間がかかりました。


うわー、私は実際に見ていたrandrangeが、私はそれが1つだけの引数で動作することに気づかなかった。よくやった!
FryAmTheEggman

4

Java、278 272バイト

Javaは最高のゴルフ言語ではなく、私も最高のゴルファーではありませんが、ここで書くのはとても楽しかったです!バグと改善点を教えてください!(単なる関数として再送信することにしました。)

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

そして、スペースとコメントを含むファイル:

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
 }

2番目のプログラムでコメントを少しタブアウトできると、読みやすくなります。ありがとう。(使用するAlt+09か、Notepad ++で
タブアウトし

d[q]+=1;これは、d[q]++;どこでも+ =を使用する代わりに、配列で直接インクリメントできるようになります。それはたくさんのキャラクターを節約するはずです。
コンパス

@Compass Alreadyは既にその変更を行いましたが、ありがとう!
DeadChex

1
また::Dにfor(;t>0;t--){ 変更可能for(;t-->0;){
コンパス

ここで最初のゴルフおめでとうございます!:D Now ....宣言を少し並べ替えて、結果を(印刷する代わりに)返すだけで、これをかなり減らすことができます。まだやるべきことがあるかもしれませんが、私は行かなければなりません。ここでは244バイトのバージョンがあります: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]

@Viozに、より短い作り方を見つけてくれたことに感謝します。そして、Dそれnotが通常ゴルフに適していることを再度証明します。また、説明を書くために。

私はPythで同様のプログラムを作成しようとしましたが、私がやろうとしていたことにスコープの問題があるようです。これはかなり単純にドミノを実装し、関数Uは地震を伝播します。減算方向はU自然にラップアラウンドするため、modは必要ありません。最後の要素はE、ゼロが1に変わる回数をカウントするため、最後に印刷されません。

Ungolfed +説明:

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
変更D[r]=not eするには、D[r]=e<12つのバイトを保存し、E=[0]*-~kためにE=D+[0]170にあなたを取得するには、別の2を節約
カーデ

1

ES6、224 196 189 179 172

簡単なものはゴルフされましたが、まだやるべきことがいくつかあります。後で説明を入力します。また、なぜ短いnew Date%kものがうまく機能しなくなったのかを誰かが教えてくれれば、それはうれしいことです。

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}

使用法は

f(10, 1000);

を削除できnewます。あなたはそれを必要としないtその最後の二つのループのため、不要に;
オプティマイザ

@Optimizerあなたが引き起こすヒーロー
コンパス

a[r]^=1初期値がの場合、1または0
オプティマイザー

1

Perl、212

前のバージョンでは、正しくラッピングが行われていなかったため、実装には多少の手間がかかりました。

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}

これはおそらくこれに適したアルゴリズムではありませんが、今は考えられません。改変されていないバージョンは以下のとおりです。

ゴルフをしていない:

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バイト

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

まあ、これはあまり競争的ではありません。しかし、十分な時間がかかったので、とにかく投稿すると思いました。

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.

オンラインで試す

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.