首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使表示天气的3x3矩阵(9x9矩阵)在sudoku板上包含x

如何使表示天气的3x3矩阵(9x9矩阵)在sudoku板上包含x
EN

Stack Overflow用户
提问于 2022-11-25 07:14:40
回答 1查看 27关注 0票数 1

我在python中创建一个Sudoku,我需要创建一个3x3矩阵,其中每个值都代表板上的一个框。如果方框中有一个值实例,则该值将为False,如果没有,则为True。

目前我有

代码语言:javascript
复制
temp_board = ma.masked_where(board == value, board, True)
boxes = np.full((3, 3), False)
for x in range(3):
    for y in range(3):
        boxes[x, y] = not np.any(temp_board.mask[x * 3:(x + 1) * 3, y * 3:(y + 1) * 3])

板是包含数字0-9的9x9矩阵,但数值只能等于1-9。

下面是输出应该是什么样子的示例

代码语言:javascript
复制
# input
board = np.array([[4, 0, 9, 0, 7, 2, 0, 1, 3],
                  [7, 0, 2, 8, 3, 0, 6, 0, 0],
                  [0, 1, 6, 0, 4, 9, 8, 7, 0],
                  [2, 0, 0, 1, 0, 0, 0, 6, 0],
                  [5, 4, 7, 0, 0, 0, 2, 0, 0],
                  [6, 9, 0, 0, 0, 4, 0, 3, 5],
                  [8, 0, 3, 4, 0, 0, 0, 0, 6],
                  [0, 0, 0, 0, 0, 3, 1, 0, 0],
                  [0, 6, 0, 9, 0, 0, 0, 4, 0]])
value = 9
# output

[[False False  True]
 [False  True  True]
 [ True False  True]]

我正在使用的方法是工作,但效率非常低,我想知道是否有更快的方法来做到这一点。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-25 08:32:28

有一种方法,不是很微妙,而是快速,就是有一个查找索引表。

代码语言:javascript
复制
look=np.zeros((9,9,9), dtype=bool)
look[0,:3,:3]=True
look[1,:3,3:6]=True
look[2,:3,6:]=True
look[3,3:6,:3]=True
look[4,3:6,3:6]=True
look[5,3:6,6:]=True
look[6,6:,:3]=True
look[7,6:,3:6]=True
look[8,6:,6:]=True

def inblock(board, blnum, val):
    return val in board[look[blnum]]

为了直接得到矩阵,你可以

代码语言:javascript
复制
~(look*board == value).any(axis=(1,2)).reshape(3,3)

look*board是一个9x9x9矩阵,每个块只过滤一个块((look*board)[k]在任何地方都包含0,但在块k中,这是板的副本)。

(look*board == value)是它的一个布尔版本。

所以(look*board == value).any(axis=(1,2))是9个值,真当且仅当block[k] contains value

因为我使用了一个一维块数组,你可以重塑得到3x3矩阵。

然后否定结果来模仿你的输出。

请注意,构建look表肯定有更微妙的方法。例如,使用您自己的For循环,稍微修改一下。但那只需要一次。

替代方案

更直截了当(坦白地说,当我开始思考你的问题时,我想要的是:

代码语言:javascript
复制
look=np.zeros((3,3,9,9), dtype=bool)
for i in range(3):
    for j in range(3):
        look[i,j,i*3:(i+1)*3,j*3:(j+1)*3] = True

~np.einsum('ijkl,kl', look, board==value)

事实上,我使用(3,3,9,9)形状,然后避免整形实际上不是重点(这是相同的成本,只是一个演示问题)。对于以前的解决方案我本可以这么做的。

这一次,我使用一个双循环来创建look表,这也不是事实。再说一遍,我以前也可以这么做的。改变的不是look。只是einsum的用法。这并不比我以前的解决方案好。但这是我最初的想法:使用一种矩阵乘法。

时差

~(look*board == value).any(axis=(2,3)):18.9μs (注:这是我以前的解决方案,适合于(3,3,9,9)形状

~np.einsum('ijkl,kl', look, board==value):13.6μs

所以,我的第二个解决方案不仅仅是我想要的那个。但它似乎也更快。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74569356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档