지진 분석


17

배경

랜덤 도미노 오토 마톤 셀룰러 오토마타에서 영감 지진 장난감 모델이다. 이 과제에서이 모델의 단순화 된 버전을 시뮬레이션하고 해당 모델에서 데이터를 수집해야합니다.

오토 마톤은 비트 배열 A로 정의 k되며 지진이 발생할 수있는 결함 라인을 나타냅니다. 배열은 경계를 둘러 쌉니다. 조건의 A[i] = 0위치가 있음을 의미 i한다 완화A[i] = 1수단이 있다는 흥분 , 또는 에너지를 저장 포함되어 있습니다. 각각의 시간 단계에서, 어레이의 하나의 위치는 무작위로 균일하게 선택된다. 해당 위치가 완화되면 흥분됩니다 (잠재 에너지가 시스템에 추가됨). 해당 위치가 이미 여기 된 경우 지진이 발생하고 선택한 위치와 여기에 연결된 모든 여기 된 위치가 다시 완화됩니다. 이완되는 흥분된 위치의 수는 크기입니다 는 지진 입니다.

배열을 고려하십시오

100101110111

랜덤 프로세스가 왼쪽에서 두 번째 비트를 선택하면 배열은 다음과 같이 업데이트됩니다.

110101110111
 ^

(표시 선택된 비트 이후 ^)이었다 0. 다음으로 왼쪽에서 네 번째 비트 인 isolated 1를 선택하면 크기 1의 eartquake가 트리거되고 비트가 0다시 설정 됩니다.

110001110111
   ^

다음으로 오른쪽에서 두 번째 비트를 선택하면 5의 지진이 발생합니다.

000001110000
          ^

모든 것이 1선택한 것과 동일한 "클러스터"에있는 s는 지진의 일부였으며 배열은 경계에서 둘러싸입니다.

작업

두 개의 양의 정수를 입력으로 취해야 k하며 t, 모든 s의 t초기 길이 k배열 부터 시작하여 시간 단계에 대해 무작위 도미노 자동 장치를 시뮬레이션하는 것이 임무입니다 0. 당신의 결과는 정수 의 목록 L이 되어야하며 k, 여기서 L[i](1 기반 색인으로) 지진의 수를 포함합니다.i 을 사용하면 시뮬레이션 중에 발생한 됩니다. 출력에서 후행 0을 제거 할 수 있습니다.

입력 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 좋은 생각, 업데이트되었습니다.
Zgarb

답변:


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 스택 (발 K 위에 t 대가) 잎 원하는 배열.

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

파이썬 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 's 와 거의 동일한 솔루션을 가지고 있었지만 조금 더 비틀 거리는 것으로 나타났습니다.


와우 실제로 보았지만 randrange하나의 인수로만 작동한다는 것을 알지 못했습니다. 잘 했어!
FryAmTheEggman 2016 년

4

자바, 27272 바이트

자바는 최고의 골프 ​​언어가 아니며, 나는 최고의 골퍼가 아니지만, 여기에 글을 쓰는 것은 많은 재미였습니다! 버그 및 개선 사항에 대해 알려주세요! (단지 함수로 다시 제출하기로 결정했습니다.)

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
 }

두 번째 프로그램에서 주석을 약간 탭하면 가독성에 도움이 될 수 있습니다. 감사. (을 사용 Alt+09하거나 메모장에서 탭 ++)
mbomb007

d[q]+=1;이것은 d[q]++;어디서나 + =를 사용하는 대신 배열에서 직접 증가시킬 수 있습니다. 그것은 많은 문자를 저장해야합니다.
Compass

@Compass 이미 변경했습니다. 감사합니다!
DeadChex

1
또한 : for(;t>0;t--){ 로 변경 가능 for(;t-->0;){: D
Compass

첫 골프를 축하합니다! : D Now .... 선언을 약간 재정렬하고 결과를 (인쇄하는 대신) 반환하면이 부분을 상당히 줄일 수 있습니다. 더해야 할 일이 있지만 가야합니다. 여기에 244 바이트 버전이다 : pastebin.com/TWAXvyHW
Geobits

4

파이썬 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]

더 짧은 방법을 찾아서 D다시 증명할 수있는 @Vioz에게 감사드립니다 not. 또한 설명을 작성합니다.

나는 Pyth에서 비슷한 프로그램을 만들려고 시도했지만 내가하려는 일에 범위 문제가있는 것 같습니다. 이것은 도미노를 순진하게 구현하며이 기능은 U지진을 전파합니다. 빼기 방향은 U자연스럽게 둘러싸 기 때문에 모드가 필요하지 않습니다. 마지막 요소는 E0이 1로 바뀌는 횟수 를 계산하므로 끝에 인쇄되지 않습니다.

언 골프 + 설명 :

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]*-~kE=D+[0]또 다른 2를 저장, (170)에 당신을 얻을
카데

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. tfor 루프에서 필요하지 않습니다. 마지막 두 개가 필요 하지 않습니다;
Optimizer

@Optimizer 당신은 영웅이 발생
나침반

a[r]^=1초기 값이 하나 인 경우 작업을 인증 된 정의됩니다 1또는0
최적화

1

펄, 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}

이것은 아마도 올바른 알고리즘이 아니지만 지금은 생각할 수 없습니다. 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 바이트

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.