Phân tích động đất


17

Lý lịch

Các Random Domino Automaton là một mô hình đồ chơi cho động đất, lấy cảm hứng từ cellular automata. Trong thử thách này, nhiệm vụ của bạn là mô phỏng một phiên bản đơn giản hóa của mô hình này và thu thập dữ liệu từ mô hình đó.

Máy tự động được xác định trên một mảng Acác kbit, đại diện cho một dòng lỗi mà động đất có thể xảy ra. Các mảng bao quanh tại biên giới của nó. Điều kiện A[i] = 0có nghĩa là vị trí đó iđược thư giãnA[i] = 1có nghĩa là nó bị kích thích hoặc chứa năng lượng dự trữ. Ở mỗi bước thời gian, một vị trí của mảng được chọn thống nhất một cách ngẫu nhiên. Nếu vị trí đó được thư giãn, nó sẽ trở nên phấn khích (năng lượng tiềm năng được thêm vào hệ thống). Nếu vị trí đó đã được kích thích, nó sẽ gây ra một trận động đất, và vị trí được chọn và tất cả các vị trí kích thích được kết nối với nó sẽ được thư giãn trở lại. Số lượng các vị trí phấn khích trở nên thư giãn là cường độ của trận động đất.

Thí dụ

Hãy xem xét các mảng

100101110111

có độ dài 12. Nếu quá trình ngẫu nhiên chọn bit thứ hai từ bên trái, mảng được cập nhật thành

110101110111
 ^

vì bit đã chọn (được đánh dấu bằng ^) là 0. Nếu chúng ta tiếp theo chọn bit thứ tư từ bên trái, đó là một cô lập 1, một tai nghe có cường độ 1 được kích hoạt và bit được đặt 0lại:

110001110111
   ^

Tiếp theo, chúng ta có thể chọn bit thứ hai từ bên phải, điều này gây ra trận động đất mạnh 5 độ:

000001110000
          ^

Lưu ý rằng tất cả các 1s trong cùng một "cụm" như nhóm được chọn là một phần của trận động đất và mảng bao quanh ở đường viền.

Nhiệm vụ

Bạn sẽ lấy đầu vào là hai số nguyên dương kt, nhiệm vụ của bạn là mô phỏng máy tự động domino ngẫu nhiên cho tcác bước thời gian, bắt đầu từ một kmảng dài ban đầu của tất cả các 0s. Đầu ra của bạn sẽ là một danh sách Lcác ksố nguyên, trong đó L[i](với lập chỉ mục dựa trên 1) chứa số lượng các trận động đất có cường độ ixảy ra trong quá trình mô phỏng. Bạn được phép thả các số 0 ở cuối từ đầu ra.

Đối với đầu vào k = 15t = 1000, một số đầu ra đại diện là

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

Quy tắc

Cả hai chương trình và chức năng đầy đủ đều được cho phép. Số byte ngắn nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

Lưu ý rằng bạn không bắt buộc phải mô phỏng thiết bị tự động bằng cách sử dụng bất kỳ triển khai cụ thể nào, chỉ có vấn đề đầu ra.


2
Có thể là bạn có thể thêm một dấu mũ ^ dưới bit thay đổi? Nó có thể giúp dễ hình dung ví dụ hơn
DeadChex

1
@DeadChex Ý tưởng hay, cập nhật.
Zgarb

Câu trả lời:


2

Bình thường, 48 byte

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

Có một chút cảm hứng từ lời giải thích của @ Dennis. Có một vài suy nghĩ tương tự ngày hôm qua, nhưng không thực sự theo chúng.

Dùng thử trực tuyến: Trình diễn

Giải trình:

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

Đây là một hàm ẩn danh bật kt từ ngăn xếp ( k trên đỉnh t ) và trả lại mảng mong muốn.

Hãy thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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

Hóa ra tôi đã có giải pháp gần như tương tự với Fry , nhưng với một chút khó khăn hơn.


Wow tôi đã thực sự nhìn vào randrange, nhưng tôi không nhận ra nó chỉ hoạt động với một đối số. Công việc tốt đẹp!
FryAmTheEggman

4

Java, 278 272 byte

Java không phải là ngôn ngữ Golf tốt nhất và tôi không phải là người chơi golf giỏi nhất, nhưng thật vui khi viết nó ở đây! Hãy cho tôi biết về lỗi và cải tiến! (Tôi quyết định gửi lại chỉ là một chức năng.)

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

Và các tập tin với không gian và ý kiến:

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
 }

Nếu bạn có thể đánh dấu các bình luận một chút trong chương trình thứ 2, điều đó có thể giúp dễ đọc. Cảm ơn. (Sử dụng Alt+09hoặc tab nó trong Notepad ++)
mbomb007

d[q]+=1;điều này có thể trở thành d[q]++;bạn có thể tăng trực tiếp trên mảng thay vì sử dụng + = ở mọi nơi. Điều đó sẽ cứu một loạt các nhân vật.
La bàn

@Compass Đã thực hiện thay đổi đó, cảm ơn!
DeadChex

1
Ngoài ra: for(;t>0;t--){ có thể đổi thành for(;t-->0;){: D
La bàn

Chúc mừng bạn đã chơi golf đầu tiên tại đây! : D Bây giờ .... bằng cách sắp xếp lại các khai báo một chút và trả lại (thay vì in) kết quả, bạn có thể nhận được điều này khá ít. Có thể còn nhiều việc phải làm, nhưng tôi phải đi. Đây là phiên bản 244 byte: pastebin.com/TWAXvyHW
Geobits

4

Con trăn 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]

Cảm ơn @Vioz vì đã tìm ra một cách ngắn hơn để thực hiện Dvà chứng minh một lần nữa đó notthường là chơi gôn. Và cũng để viết lời giải thích.

Tôi đã cố gắng thực hiện một chương trình tương tự ở Pyth, nhưng dường như có một vấn đề phạm vi trong những gì tôi đang cố gắng thực hiện. Điều này khá ngây thơ thực hiện các domino và chức năng Utruyền động đất. Hướng trừ trong Ukhông cần mod vì nó sẽ quấn quanh một cách tự nhiên. Yếu tố cuối cùng củaE đếm số lần số 0 được chuyển thành số một, do đó, phần này không được in ở cuối.

Ungolfed + Giải thích:

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
Thay đổi D[r]=not eđể D[r]=e<1tiết kiệm 2 byte và E=[0]*-~kđể E=D+[0]tiết kiệm thêm 2 byte, để giúp bạn giảm xuống 170.
Kade

1

ES6, 224 196 189 179 172

Các công cụ dễ dàng đã được chơi golf, nhưng vẫn còn một số việc phải làm. Tôi sẽ gõ một lời giải thích sau. Ngoài ra, nếu ai đó có thể cho tôi biết lý do tại sao new Date%kđiều ngắn không còn hoạt động tốt nữa, thì đó sẽ là sưng lên.

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}

Cách sử dụng là

f(10, 1000);

Bạn có thể loại bỏ new. Bạn không cần điều đó ttrong vòng lặp for, Không cần hai lần cuối đó;
Trình tối ưu hóa

@Optimizer bạn là người hùng gây ra
La bàn

a[r]^=1sẽ defs hoạt động nếu giá trị ban đầu là 1hoặc0
Trình tối ưu hóa

1

Perl, 212

Phiên bản trước tôi đã đưa ra không phải là gói chính xác, và thực hiện đã mất một số công việc.

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}

Đây có lẽ không phải là thuật toán phù hợp cho việc này, nhưng tôi không thể nghĩ ngay bây giờ. Các phiên bản không linh hoạt là dưới đây.

Ung dung:

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

Vâng, điều này không phải là rất cạnh tranh. Nhưng vì tôi đã mất đủ lâu, tôi nghĩ dù sao tôi cũng sẽ đăng nó.

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.

Dùng thử trực tuyến

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.