给定N×N网格,计算5个连续空间的所有可能序列

时间:2018-03-10 19:04:08

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

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

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

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

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

我们还可以假设N的值是事先知道的。

我对此问题的初步处理包括从头开始循环遍历整个网格,检查水平序列,然后检查垂直序列,然后检查对角线序列。然而,这将被证明是低效的,因为我必须每次不断地重新计算序列的长度,确保它们等于5以及检查序列是否是连续的。

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

任何指导都将不胜感激!

1 个答案:

答案 0 :(得分: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

E.g。

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

enter image description here

  

注意,返回大于或等于链的序列;并不限制自己只有5个长度的序列。将其更改为只有5的长度是一个微不足道的修复。