【问题标题】:Modifying matrix. Very interesting task for python [closed]修改矩阵。 python非常有趣的任务[关闭]
【发布时间】:2019-08-03 00:44:35
【问题描述】:

假设我们有以下列表

mag = [
    [0, 1, 1, 1],
    [0, 1, 0, 1],
    [1, 1, 0, 1],
    [0, 1, 0, 1],
]

问题:需要添加或合并新行,如[1, 0, 0, 1]

规则:如果我添加与某些行重叠的列表,则应根据与提供的项目重叠的项目来附加或合并它。

示例(开头的mag矩阵):

mag.add([0, 0, 1, 0])
[
    [0, 1, 1, 1], # << -- here is were overlapped
    [0, 1, 1, 1], # << -- here will be merged
    [1, 1, 0, 1],
    [0, 1, 0, 1],
]

示例2(开头的mag矩阵):

mag.add([0, 1, 0, 0])
[
    [0, 1, 1, 1],
    [0, 1, 0, 1],
    [1, 1, 0, 1],
    [0, 1, 0, 1], # << -- overlaps first list from end, will be appended
    [0, 1, 0, 0],
]

示例3(开头的mag矩阵):

mag.add([1, 0, 0, 0])
[
    [0, 1, 1, 1],
    [0, 1, 0, 1],
    [1, 1, 0, 1], # << -- overlaps here
    [1, 1, 0, 1], # << -- here were merged
]

为了更清楚,假设这是俄罗斯方块,其中[0, 1, 0, 1] 之类的新列表是一个图形,其中1 是一个块,0 是一个空闲空间。如果图形从底部移动到顶部,我们需要了解图形可能在哪里。

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 我试图思考如何在不遍历所有列表的情况下实现它。
  • 我不明白您如何确定要合并的行,看起来您并不总是从列表的同一端开始。
  • 有点像俄罗斯方块,但从底部开始,1是块,0是空闲空间。

标签: python arrays list matrix


【解决方案1】:

在这里,我们从末尾循环遍历矩阵,检查每一行是否重叠。如果是,我们编辑上一行。如果它到达矩阵的顶部,我们合并顶行。

def overlap(a, b):
    return any(x&y for x, y in zip(a, b))

def merge(a, b):
    return [x|y for x, y in zip(a, b)]

def update_matrix(mat, row):
    if overlap(mat[-1], row): # If the new row doesn't fit at all, add it at the end
        mat.append(row)
        return
    for ind, line in enumerate(reversed(mat)):
        if overlap(line, row):
            change_index = ~(ind-1)  # This trick uses negative indexing to index 
                                     # from the end of the list
            break  # We have the row to merge
    else:
        change_index = 0  # We got to the top, so we need to change the first row
    mat[change_index] = merge(mat[change_index], row)

【讨论】:

  • 哇!有用!谢谢!
  • 使用 numpy 怎么样? =)
  • 我的 numpy 很弱。我要注意的一件事是,如果您将这些数组视为二进制数/位数组,则 overlapa&amp;b != 0mergea|b。这似乎是 numpy 可以做的事情。
  • 是的,稍后会尝试适应。现在只需要一个快速的解决方案。非常感谢男士们。
【解决方案2】:

这是一个使用 numpy 的矢量化解决方案。一般的想法是通过检查几个条件来更新mag。首先mag必须是0,上面的值也必须是1,更新将应用于新行包含1的列。

一般的解决方法如下:

def add(x, row):
    import numpy as np
    # Check that the row above contains a 1
    c1 = np.roll(x, 1, axis = 0) == 1
    # Coordinates on where to update with a 1
    ix_x, ix_y = (c1 & (x == 0) & (np.array(row) == 1)[:,None].T).nonzero()
    # If any values satisfy the condition update with a 1
    if ix_x.size > 0:
        mag[ix_x.min(), ix_y] = 1
    else:
        # Otherwise stack the new row at the end
        x = np.vstack([x, row])
    return x

现在让我们看看 3 个建议的例子:

# Example 1
row = [0, 0, 1, 0]
add(mag,row)
array([[0, 1, 1, 1],
       [0, 1, 1, 1],
       [1, 1, 0, 1],
       [0, 1, 0, 1]])

# Example 2
row = [0, 1, 0, 0]
add(mag,row)
array([[0, 1, 1, 1],
       [0, 1, 0, 1],
       [1, 1, 0, 1],
       [0, 1, 0, 1],
       [0, 1, 0, 0]])

# Example 3
row = [1, 0, 0, 0]
add(mag,row)
array([[0, 1, 1, 1],
       [0, 1, 0, 1],
       [1, 1, 0, 1],
       [1, 1, 0, 1]])

【讨论】:

  • 稍后会检查。
猜你喜欢
  • 2018-05-10
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-05
相关资源
最近更新 更多