【问题标题】:Given a N×N grid, compute all possible sequences of 5 consecutive spaces给定一个 N×N 网格,计算 5 个连续空间的所有可能序列
【发布时间】:2018-03-10 19:04:08
【问题描述】:

给定一个 N×N 网格,其中网格中的所有位置都标记为“是”、“否”或“”(空格)。

在包含 5 个连续“”(空格)的网格中查找所有可能的序列。这里的“连续空间”可以是垂直的、水平的或对角的。

我们可以假设网格表示为一个字典,其中字典的每个键都代表一个位置作为坐标,每个值代表该位置是否有“是”、“否”或“” .

例如,grid[(1, 2)] = "是"。表示在网格上的位置 (1, 2) 处有一个“是”。

我们也可以假设 N 的值是预先知道的。

我最初解决这个问题的方法是从头开始遍历整个网格,检查水平序列,然后是垂直序列,然后是对角序列。但是,这将被证明是低效的,因为我每次都必须不断地重新计算序列的长度,确保它们等于 5 并检查序列是否连续。

我一直在寻找一种更优雅的方法,一种更好的方法来做到这一点。是否有允许进行此类计算的 Python 库?我试过寻找,但没有找到任何符合问题限制的东西。

任何指导将不胜感激!

【问题讨论】:

  • 你的努力在哪里?

标签: python python-3.x python-2.7 matrix grid


【解决方案1】:

使用scipy;具体来说,使用scipy.ndimage.label 函数,它将连接的序列标记在一起。

import scipy, scipy.ndimage


# N and grid dictionary are already known
G = scipy.zeros([N,N])
for k, v in grid.iteritems():
    if v.lower() == 'yes':
        G[tuple(k)] = 1
    elif v.lower() == 'no':
        G[tuple(k)] = -1

def get_consecutive_spaces(G, chain=5):

    sequences = []

    # Generate a pattern for each directional sequence. (1) Horizontal,
    # (2) vertical, (3) top-left to bottom-right diagonal, (4) bottom-left
    # to top-right diagonal
    patterns = [scipy.ndimage.label(G == 0, structure = scipy.array([[0,0,0],
                                                                     [1,1,1],
                                                                     [0,0,0]])),
                scipy.ndimage.label(G == 0, structure = scipy.array([[0,1,0],
                                                                     [0,1,0],
                                                                     [0,1,0]])),
                scipy.ndimage.label(G == 0, structure = scipy.array([[1,0,0],
                                                                     [0,1,0],
                                                                     [0,0,1]])),
                scipy.ndimage.label(G == 0, structure = scipy.array([[0,0,1],
                                                                     [0,1,0],
                                                                     [1,0,0]]))]

    # Loop over patterns, then find any labelled sequence >= a size of chain=5
    for lab_arr, n in patterns:
        for i in range(1, n+1):
            b = lab_arr == i
            b_inds = scipy.where(b)
            if len(b_inds[0]) < chain:
                continue

            sequences.append((tuple(b_inds[0]), tuple(b_inds[1])))

    return sequences

例如

>>> G = scipy.sign(scipy.random.random([12,12]) - 0.5)*(scipy.random.random([12,12]) < 0.5)
>>> print G
[[-0.  1. -1.  1.  1. -1.  1.  0. -0.  1.  0. -0.]
 [ 1.  1. -0. -0. -1.  1.  1. -1. -1.  1. -0. -1.]
 [ 0.  1.  1.  1.  0.  1. -0.  0.  0.  0. -0.  0.]
 [ 1. -0. -1.  0. -1. -0.  1.  0. -0. -0. -0.  1.]
 [-0.  1. -1.  1. -0. -0. -1. -0.  1.  1. -0.  0.]
 [ 0. -1.  1. -0.  1.  0. -0. -1. -1. -0.  0. -1.]
 [-1. -0.  0. -1. -1. -0. -1.  0.  0.  0. -1.  0.]
 [-0.  1.  0.  0.  0.  1.  1. -1.  0. -0. -1.  0.]
 [ 1.  1.  0.  1. -1. -1.  0.  0. -1.  1.  0.  0.]
 [-0.  0.  0. -1. -0. -1.  1. -0.  0.  1.  1.  0.]
 [-1.  1. -1.  1.  0.  1.  0.  1.  1.  1.  1.  0.]
 [-1.  1. -0.  0. -1.  0. -0. -1.  1. -1. -0.  0.]]

>>> sequences = get_consecutive_spaces(G)
>>> for s in sequences: print s
((2, 2, 2, 2, 2, 2), (6, 7, 8, 9, 10, 11))
((0, 1, 2, 3, 4, 5), (10, 10, 10, 10, 10, 10))
((6, 7, 8, 9, 10, 11), (11, 11, 11, 11, 11, 11))
((0, 1, 2, 3, 4, 5, 6, 7), (11, 10, 9, 8, 7, 6, 5, 4))
((2, 3, 4, 5, 6), (6, 5, 4, 3, 2))
((4, 5, 6, 7, 8), (11, 10, 9, 8, 7))

注意,返回大于或等于链的序列;不将自身限制为长度仅为 5 的序列。将其更改为仅 5 的长度是一个简单的修复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 2014-12-25
    • 2015-10-30
    • 2011-05-27
    相关资源
    最近更新 更多