checkio Life Counter

#康威生命游戏#checkio#python益智游戏

生命的游戏 , 也简称为生命,是一种“游戏”或元胞自动机 由英国数学家约翰·霍顿·康威(John Horton Conway)于1970年设计。 “游戏”是一个零玩家游戏,这意味着它的进化是由它的初始状态决定的, 不需要进一步的输入。一个人通过创建一个首字母来与生命游戏互动 配置并观察它是如何演变的,或者对于高级玩家来说,通过创建模式 特定属性。

生命游戏中的宇宙是一个无限的二维正交方格网格, 它们中的每一个都处于两种可能的状态之一,活着或死去。每个细胞都与其相互作用 八个相邻单元,它们是水平、垂直或对角线相邻的单元格。 在时间的每个步骤中,都会发生以下转变:
- 任何少于两个活邻居的活细胞都会死亡,就好像是由人口不足引起的一样。
- 任何具有两个或三个活邻居的活细胞都会延续到下一代。
- 任何有三个以上活邻居的活细胞都会死亡,就好像过度拥挤一样。
- 任何具有三个活邻居的死细胞都会变成活细胞,就像通过繁殖一样。

初始模式(或第 0 步)构成了系统的种子。 第一代是通过同时应用上述规则创建的 对种子中的每一个细胞来说——出生和死亡同时发生, 发生这种情况的离散时刻有时称为刻度 (换句话说,每一代都是前一代的纯函数)。 这些规则继续被反复应用,以创造后代。

在此任务中,您应该计算在第 N 个刻度时网格上将有多少个活细胞。 您将获得一个初始位置(带有活细胞的网格片段) 作为矩阵和刻度 的数字。 矩阵表示为元组元组,其中 1 是活单元格,0 是死单元格。 不要忘记网格在每个方向上都是无限的

在此示例中,初始位置将表示为:

((0, 1, 0, 0, 0, 0, 0),
 (0, 0, 1, 0, 0, 0, 0),
 (1, 1, 1, 0, 0, 0, 0),
 (0, 0, 0, 0, 0, 1, 1),
 (0, 0, 0, 0, 0, 1, 1),
 (0, 0, 0, 0, 0, 0, 0),
 (1, 1, 1, 0, 0, 0, 0),)

如果我们需要计算第 4 步的活细胞, 那么从上图中可以看出,答案是 15。

输入: 两个论点。 初始状态为具有整数(0 或 1)的元组元组,并且 整数 (N) 表示为整数的数字。

输出: 第 N 个刻度的活像元数,以整数形式表示。

例:

life_counter(((0100, 0, 000),
00100, 0, 0),
1110, 0, 00),
0000011),
0000011),
0000, 0, 00),
1110000)), 4) == 15

使用方法: 这个游戏是元胞自动机的一个例子。 这是一个很好的建模工具。您可以添加图形和 如果你愿意,把它变成你自己的“生活”游戏。

前提条件: 0 < tick_n < 1000
3 ≤ len(state) ≤ 20
all(len(row) == len(state[0]) for row in state)

def neighbours(index):
    """参数接受一个索引,最后返回一个迭代对象,指向该位置周边的位置索引"""
    for dx in [-1, 0, 1]:
        for dy in [-1, 0, 1]:
            if dx != 0 or dy != 0:
                yield index[0] + dx, index[1] + dy


def neighbour_count(scope, cell):
    """参数为筛选范围和某细胞,函数用于返回某细胞cell周边存在于scope范围内的周边cell的个数"""
    return sum(cell in scope for cell in neighbours(cell))


def tick(scope):
    """接受一个scope作为范围参数,通过对范围内和范围外的细胞使用neighbour_count和neighbour函数判断该迭代情况下,生死细胞的情况"""
    life, dead = set(), set()
    # 收集能够存活的细胞
    # 从参数scope范围内获取元素,注意:在life_counter函数中,即是从liveCell活细胞集中获取活细胞的坐标
    for cell in scope:
        # 注意:在life_counter函数中,该循环即计算一个活细胞的周边所有活细胞的个数
        num = neighbour_count(scope, cell)
        if num == 2 or num == 3:
            life.add(cell)
        # 所有scope中的cell的周边细胞组成的细胞集定然大于scope,将cell周边超出scope范围的定义为死细胞,求并集
        dead |= {neighbor for neighbor in neighbours(
            cell) if neighbor not in scope}
    # 检索死细胞周围的活细胞个数,判断死细胞可能转化为活细胞的情况
    for cell in dead:
        # 接受一个死细胞作为cell参数检索该细胞周围存在的活细胞
        if neighbour_count(scope, cell) == 3:
            life.add(cell)
    # 最后返回活细胞
    return life


def life_counter(state, tick_n):
    """
    定义此函数接受一个state矩阵,和迭代次数。从state中获取所有活细胞的位置作为liveCell,
    然后进入迭代状态,使用tick函数返回所有得到活细胞位置,最后返回活细胞个数
    """
    # 遍历整个state同时将所有cell中的真值即livecell位置添加到集合中
    liveCell = {(index_x, index_y) for index_x, row in enumerate(state)
                for index_y, char in enumerate(row) if char}
    # 根据参数tick_n来决定进行几代
    for times in range(tick_n):
        # 将liveCell作为范围参数scope传入tick函数,tick函数得以检索每一个细胞存活的情况
        liveCell = tick(liveCell)
    return len(liveCell)


life_counter(((0, 1, 0, 0, 0, 0, 0),
              (0, 0, 1, 0, 0, 0, 0),
              (1, 1, 1, 0, 0, 0, 0),
              (0, 0, 0, 0, 0, 1, 1),
              (0, 0, 0, 0, 0, 1, 1),
              (0, 0, 0, 0, 0, 0, 0),
              (1, 1, 1, 0, 0, 0, 0)), 4)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值