最近在ChinaUnix的Shell论坛上,看到了一篇细胞分裂游戏的帖子,觉得很有趣。但看完题目后却不知该如何下手,于是研究了一下yestreenstars和yinyuemi两位大神提供的实现脚本。大神不愧为大神,实现可以如此简单。
以下为我依据yestreenstars的脚本做了一些细微修改(代码优化方面的,比如少用个变量什么的),功能上的修改主要是原先在100代之前,所有细胞死亡不会打印最后的统计信息,而现在可以打印(其实也是非常细小的修改 -_-!)。
好,现在上题目:
我们用以下4个字符/字符串来表示细胞的生命周期:
o -> 0 -> 8 -> oo
幼年期 -> 成年期 -> 分裂期 -> 两个幼体
以一秒代表一年,其中在各个生命周期中的细胞在一年中可能的变化如下:
幼年期:
1/10的概率死亡 o -> .
4/5的概率长大 o -> 0
1/10的概率不变 o -> o
成年期:
1/10的概率死亡 0 -> .
4/5的概率分裂 0 -> 8
1/10的概率不变 0 -> 0
分裂期:
1/10的概率死亡 8 -> .
4/5的概率分裂成功 8 -> oo
1/10的概率单个死亡 8 -> o.
死亡后的.在下一年中仍保留但不做任何变化。
请用shell写一个细胞分裂的世代推演脚本,每秒产生一行输出,直到第100行或者全部细胞死亡,并计算出各世代中各生命状态包括死亡的细胞的数量。
[1] o
[2] 0
[3] 8
[4] oo
[5] o0
[6] 08
[7] 8oo
...
[100] 0oo8o.80..8.oo0.8oo
---------------------------
[.] [o] [0] [8] [.o08]
[1]: 0 1 0 0 1
[2]: 0 0 1 0 1
[3]: 0 0 0 1 1
[4]: 0 2 0 0 2
[5]: 0 1 1 0 2
[6]: 0 0 1 1 2
[7]: 0 1 1 1 3
...
[100]: 5 7 3 4 20
以下为我在yestreenstars提供的实现脚本基础上修改后的脚本:
怎么上传代码无法保留缩进...
-
#!/bin/awk -f
-
-
BEGIN {
-
srand();
-
b[0] = "o"; # 初始细胞。
-
printf("[0] %s\n", b[0]);
-
for(i = 0; i++ < 100;)
-
{
-
l = split(b[i - 1], a, "");
-
for(j = 0; j++ < l;)
-
{
-
r = rand();
-
# 已死亡的细胞100%概率保持原状。
-
if(r < 0.1) # o08都有1/10概率死亡。
-
{
-
a[j] = ".";
-
}
-
else if(r < 0.2) # o0有1/10概率保持原状,而8则是变为"o."。
-
{
-
if(a[j] == "8")
-
{
-
a[j] = "o.";
-
}
-
}
-
else # 4/5概率成功进阶。
-
{
-
if(a[j] == "8")
-
{
-
a[j] = "oo";
-
}
-
if(a[j] == "0")
-
{
-
a[j] = "8";
-
}
-
if(a[j] == "o")
-
{
-
a[j] = "0";
-
}
-
}
-
}
-
for(j = 0; j++ < l;)
-
{
-
b[i] = ((b[i] != "") ? (b[i]""a[j]) : a[j]);
-
}
-
-
printf("[%d] %s\n", i, b[i]);
-
if(b[i]~/^\.+$/) # 这一代如果全死亡,下一代就没必要进行了。
-
{
-
break;
-
}
-
-
system("sleep 1");
-
}
-
print("------------------------------------------------------");
-
print("\t[.]\t[o]\t[0]\t[8]\t[.o08]");
-
for(i = 0; i++ < (length(b) - 1);)
-
{
-
f5 = length(b[i]);
-
f4 = gsub(/8/, "", b[i]);
-
f3 = gsub(/0/, "", b[i]);
-
f2 = gsub(/o/, "", b[i]);
-
f1 = f5 - f4 - f3 - f2;
-
printf "[%d]:\t%d\t%d\t%d\t%d\t%d\n", i, f1, f2, f3, f4, f5;
-
}
-
}
以下为原帖地址:
阅读(338) | 评论(0) | 转发(0) |