【问题标题】:How to create lists of 3x3 sudoku block in python如何在 python 中创建 3x3 数独块的列表
【发布时间】:2014-01-21 22:35:37
【问题描述】:

我需要帮助为数独中的 9 个 3x3 块中的每一个创建一个列表。所以我有一个代表原始数独板的列表列表(零表示空):

board=[[2,0,0,0,0,0,0,6,0],
       [0,0,0,0,7,5,0,3,0],
       [0,4,8,0,9,0,1,0,0],
       [0,0,0,3,0,0,0,0,0],
       [3,0,0,0,1,0,0,0,9],
       [0,0,0,0,0,8,0,0,0],
       [0,0,1,0,2,0,5,7,0],
       [0,8,0,7,3,0,0,0,0],
       [0,9,0,0,0,0,0,0,4]]

我需要将这些转换为包含 3x3 块的列表列表。比如:

[[2,0,0,0,0,0,0,4,8],[etc]]

我尝试创建一个名为“blocks”的列表,其中包含 9 个其他列表,每个列表中只有零。所以它看起来像:

blocks=[[0,0,0,0,0,0,0,0,0],[etc]

然后我使用 while 循环来更改列表中的值:

BLOCK_COUNT=0
BOARD_COUNT=0
while BLOCK_COUNT<len(blocks):
    blocks[BLOCK_COUNT][0]=board[BOARD_COUNT][BOARD_COUNT]
    blocks[BLOCK_COUNT][1]=board[BOARD_COUNT][BOARD_COUNT+1]
    blocks[BLOCK_COUNT][2]=board[BOARD_COUNT][BOARD_COUNT+2]
    blocks[BLOCK_COUNT][3]=board[BOARD_COUNT+1][BOARD_COUNT]
    blocks[BLOCK_COUNT][4]=board[BOARD_COUNT+1][BOARD_COUNT+1]
    blocks[BLOCK_COUNT][5]=board[BOARD_COUNT+1][BOARD_COUNT+2]
    blocks[BLOCK_COUNT][6]=board[BOARD_COUNT+2][BOARD_COUNT]
    blocks[BLOCK_COUNT][7]=board[BOARD_COUNT+2][BOARD_COUNT+1]
    blocks[BLOCK_COUNT][8]=board[BOARD_COUNT+2][BOARD_COUNT+2]
    BLOCK_COUNT+=1
    BOARD_COUNT+=3

然而,这给了我一个索引错误。如果我创建了 2 个“BLOCK_COUNT”分别为 3 和 6 的 while 循环,那么我会得到一个更好的答案,但它仍然没有给我正确的 3x3 块。所以我几乎不知道如何做到这一点。谢谢。

【问题讨论】:

  • 如果您希望我们调试您的错误,请给我们完整的错误和回溯,而不仅仅是错误的描述。
  • 不,正如我所说,我需要帮助创建 3x3 块的列表。我只是提供了有关错误的信息,认为知道我哪里出错可能很有用。我假设它不需要?
  • 因为你没有给我们足够的信息来调试你的代码,每个人都忽略了这部分,而是为你编写了全新的代码。全新的代码可能会更好——至少如果你能理解它——但是知道你哪里出错了不是很有帮助吗?

标签: python list sudoku


【解决方案1】:
def getBlocks(board):
    answer = []
    for r,c in itertools.product(range(3), repeat=2):
        answer.append([board[r+i][c+j] for i,j in itertools.product(range(0, 9, 3), repeat=2)])
    return answer

当然,您可以只用一个列表理解来替换整个内容:

answer = [[board[r+i][c+j] for i,j in itertools.product(range(0, 9, 3), repeat=2)]
          for r,c in itertools.product(range(3), repeat=2)]

如果您对不使用任何内置插件来完成繁重工作的版本感兴趣:

def getBlocks(board):
    answer = []
    for r in range(3):
        for c in range(3):
            block = []
            for i in range(3):
                for j in range(3):
                    block.append(board[3*r + i][3*c + j])
            answer.append(block)
    return answer

那么这里发生了什么?

嗯,首先,我们决定遍历我们想要的 9 个块。这些由rc 变量控制。这也是我们在访问棋盘上的数字时将它们乘以 3 的原因(因为每个块都是边 3 的正方形)。

接下来,我们要遍历每个块中的元素。翻译:查找每个 3x3 块中的数字。块内每个元素的索引由ij 管理。所以我们有ij 来管理我们想要访问的元素,还有rc,它们是它们与板本身的偏移量,确定了我们想要的“块”的位置。现在我们要去参加比赛了。

对于每个rc(请注意,每个循环都遍历range(3),因此有9 个(r,c) 对-我们之后的9 个块),循环块中的9 个元素( 9 (i,j) 对)。现在,只需根据它们从(r,c) 偏移量的相对位置访问元素(3*r 给出相关块的第一行,添加i 给出所需元素的行。类似地,3*c 给出相关块的第一列,并添加j 给出所需元素的列。因此,我们得到了我们想要的元素的坐标)。现在,我们将元素添加到block

一旦我们遍历了块中的所有元素,我们就将块本身添加到答案中,然后!我们完成了

【讨论】:

  • 有解释会更好。此外,对于新手来说,使用嵌套循环可能比product 更简单。 (仍然比我将要发布的内容更好,我使用了 3 行理解而不是理解……)
  • Ack,现在你已经添加了我的理解,但被塞进了 2 行而不是 3 行。:) 但幸运的是,你首先展示了对新手更友好的版本。
  • 对不起@abarnert,我太喜欢list-comps了
  • 最后一件事:r in range(0, 9, 3) 怎么样,所以你可以放弃3 *(以及它的解释)?向新手解释更容易,还是更难?
  • @abarnert:我想过,但我认为这类似于使用itertools.product,因为它“为你做了一些繁重的工作”。乘法让 OP 准确地看到正在发生的事情。也许,我应该在列表推导之一中使用range(0,9,3),以表明它会使工作更轻松
【解决方案2】:

当您使用numpy 时,您可以结合使用reshapetranspose

编辑 - 抱歉 - 太快按 Enter:

import numpy as np
board=[[2,0,0,0,0,0,0,6,0],
       [0,0,0,0,7,5,0,3,0],
       [0,4,8,0,9,0,1,0,0],
       [0,0,0,3,0,0,0,0,0],
       [3,0,0,0,1,0,0,0,9],
       [0,0,0,0,0,8,0,0,0],
       [0,0,1,0,2,0,5,7,0],
       [0,8,0,7,3,0,0,0,0],
       [0,9,0,0,0,0,0,0,4]]

t = np.array(board).reshape((3,3,3,3)).transpose((0,2,1,3)).reshape((9,9));
print t

输出:

[[2 0 0 0 0 0 0 4 8]
 [0 0 0 0 7 5 0 9 0]
 [0 6 0 0 3 0 1 0 0]
 [0 0 0 3 0 0 0 0 0]
 [3 0 0 0 1 0 0 0 8]
 [0 0 0 0 0 9 0 0 0]
 [0 0 1 0 8 0 0 9 0]
 [0 2 0 7 3 0 0 0 0]
 [5 7 0 0 0 0 0 0 4]]

【讨论】:

    【解决方案3】:

    应该可以,在python3中你可以用“int(m/3)*3”替换“(m/3)*3”

    [[board[(m/3)*3+i][(m%3)*3+j] for i in range(3) for j in range(3)] for m in range(9)]
    

    【讨论】:

    • 这会引发 list 索引必须是整数,而不是 float 在 python 3.4 中的异常,因为除法 m/2 产生一个浮点数而不是整数。因此,它应该是 m//3 才能产生分区的地板。
    【解决方案4】:

    这不使用内置函数,速度更快 3 嵌套 for 循环

    def get_boxes(board):
        boxes = []
        for i in range(9): 
            if i == 0 or i % 3 == 0:  
                box_set_1 = board[i][:3] + board[i + 1][:3] + board[i + 2][:3]  
                boxes.append(box_set_1)
                box_set_2 = board[i][3:6] + board[i + 1][3:6] + board[i + 2][3:6]
                boxes.append(box_set_2)
                box_set_3 = board[i][6:] + board[i + 1][6:] + board[i + 2][6:]
                boxes.append(box_set_3)
    

    【讨论】:

      【解决方案5】:
      def get_boxes(board):    
          boxes = []
          for i in range(9): 
              if i == 0 or i % 3 == 0:  
                  box_set_1 = board[i][:3] + board[i + 1][:3] + board[i + 2][:3]  
                  boxes.append(box_set_1)
                  box_set_2 = board[i][3:6] + board[i + 1][3:6] + board[i + 2][3:6]
                  boxes.append(box_set_2)
                  box_set_3 = board[i][6:] + board[i + 1][6:] + board[i + 2][6:]
                  boxes.append(box_set_3)
          return boxes
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-04
      • 2019-02-19
      • 2011-06-10
      • 2017-11-27
      • 2020-04-04
      • 1970-01-01
      • 2014-10-07
      • 1970-01-01
      相关资源
      最近更新 更多