分析地震


17

背景

随机的Domino自动机是一个地震玩具模型,通过元胞自动机的启发。在此挑战中,您的任务是模拟该模型的简化版本,并从中收集数据。

自动机定义在位阵列上Ak位阵列表示可能发生地震的断层线。数组在其边界处环绕。条件A[i] = 0意味着位置i放松,并且A[i] = 1手段,它的兴奋,或包含存储的能量。在每个时间步长,均一地随机选择阵列的一个位置。如果该位置放松,它将变得兴奋(将势能添加到系统中)。如果该位置已被激发,则将引发地震,并且所选位置和与其连接的所有激发位置将再次放松。放松的激发位置数就是地震的幅度

考虑数组

100101110111

长度为12。如果随机过程从左侧选择第二个位,则数组将更新为

110101110111
 ^

由于所选位(标有^)为0。如果我们接下来从左边选择第四位,它是一个隔离的1,则触发震级为1的地震,并且该位0再次设置为:

110001110111
   ^

接下来,我们可以从右边选择第二个位,这将触发5级地震:

000001110000
          ^

请注意,1与所选择的“群集”相同的所有“ s”都是地震的一部分,并且数组在边界处环绕。

任务

您应将两个正整数k和用作输入t,您的任务是模拟随机的多米诺自动机的t时间步长,从k所有0s 的初始长度数组开始。您的输出应Lk整数列表,其中L[i](基于1的索引)包含i模拟过程中发生的震级数。您可以从输出中删除尾随零。

对于输入k = 15t = 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 2015年

1
@DeadChex好主意,已更新。
Zgarb 2015年

Answers:


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从堆栈中弹出(kt之上),并返回所需的数组。

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,但是我没有意识到它仅适用于一个论点。干得好!
FryAmTheEggman 2015年

4

Java,278272字节

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
 }

如果您可以在第二个程序中将注释略微一点一点,则可能有助于提高可读性。谢谢。(使用Alt+09,或在Notepad ++
中将其选中

d[q]+=1;这可以使d[q]++;您可以直接在数组上递增,而无需在任何地方使用+ =。那应该节省很多字符。
罗盘

@Compass已经进行了更改,谢谢!
DeadChex 2015年

1
另外:for(;t>0;t--){ 可以更改为for(;t-->0;){:D
Compass

恭喜您在这里第一次高尔夫!:D现在....通过稍微重新排列声明并返回(而不是打印)结果,您可以将其简化很多。可能还有更多工作要做,但我必须走。这是244字节的版本:pastebin.com/TWAXvyHW
Geobits,2015年

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的次数,因此不会在最后打印。

松开+说明:

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 eD[r]=e<1节省2个字节,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,您是英雄
Compass

a[r]^=1将DEFS工作,如果初始值是10
优化

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}

这可能不是正确的算法,但我现在无法思考。未发布的版本如下。

取消高尔夫:

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.

在线尝试

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.