几天前,我发现了如何通过对collections.abc中的Mutable Sequence进行子类化来实现海关列表类的下一个示例.

class TypedList(MutableSequence):

    def __init__(self, oktypes, *args):
        self.oktypes = oktypes
        self.list = list()
        self.extend(list(args))

    def check(self, v):
        if not isinstance(v, self.oktypes):
            raise TypeError(v)

    def __len__(self): return len(self.list)

    def __getitem__(self, i): return self.list[i]

    def __delitem__(self, i): del self.list[i]

    def __setitem__(self, i, v):
        self.check(v)
        self.list[i] = v

    def insert(self, i, v):
        self.check(v)
        self.list.insert(i, v)

    def __str__(self):
        return str(self.list)

TypedList的使用示例:

    tl = TypedList(int)
    # ok
    tl.append(1)
    # next TypeError will be raised
    tl.append('1')

我的问题:

我想知道是否有方法以类似的方式实现二维数独数组(MutableSequence)类,以管理游戏中的数独数组?

为了给您一个 idea ,下面您可以看到SudokuArray(MutableSequence)的可能实现(非操作):

class SudokuArray(MutableSequence):

    def __init__(self, n_rows=9, n_columns=9, init_value=None):
        self.n_rows = n_rows
        self.n_columns = n_columns
        self.array = [[init_value for _ in range(0, self.n_columns, 1)] for _ in range(0, self.n_rows, 1)]

    def check(self, row_number, column_number, number):
        if number in self.get_row_values(row_number) or
                                         number in self.get_column_values(column_number) or
                                         number in self.get_nonet_values(row_number, column_number)):
            raise ExistentNumberError("Existent number in row, column or nonet",
                                      number, row_number, column_number)

    def __len__(self): return self.n_rows, self.n_columns

    def __getitem__(self, row_number, column_number): return self.array[column_number][row_number]

    def __delitem__(self, row_number, column_number): del self.array[column_number][row_number]

    def __setitem__(self, row_number, column_number, number):
        self.check(number, row_number, column_number)
        self.array[column_number][row_number] = number

    def insert(self, row_number, column_number, number):
        self.check(row_number, column_number, number)
        self.array.insert(row_number, column_number, number)

    def __str__(self):
        return str(self.array)

    def get_row_values(self, row_number):
        # todo implement get_row_values method
        pass

    def get_column_values(self, column_number):
        # todo implement get_column_values method
        pass

    def get_nonet_values(self, row_number, column_number):
        # todo implement get_nonet_values method
        pass

class ExistentNumberError(Exception):
    def __init__(self, message, number, row_number, column_number):
        super().__init__(message)
        self.number = number
        self.row_number = row_number
        self.column_number = column_number

SudokuArray的使用示例:

    sudoku_array = SudokuArray()
    sudoku_array[0][0] = 1
    # next ExistentNumberError will be raised
    sudoku_array[0][0] = 1

当然,我可以使用numpy.Array,但我认为我们的9 x9数组对于使用numpy来说非常简单.我还想避免依赖性.

有主意吗?

推荐答案

您的try 中存在这些问题:

  • check中的if陈述缺乏开头括号.
  • __len__应该返回一个数字,而不是二元组.
  • __getitem__和类似的方法不应该采用两个索引参数,而应该采用一个.然而,此参数可以是一个(2个坐标的)二元组
  • __setitem__中,对self.check的调用有顺序错误的参数.
  • 数独总是具有相同的行和列数,因此我不会为行数和列数有单独的构造函数参数.只有一个参数.
  • insert__delitem__方法不应用于数独:您不想更改任何行上的条目数.在下面的更正中,我仍然会包括它们,因为也许您有充分的理由这样做?
  • get_***_values种方法没有实施.

以下是建议的代码:

from collections.abc import MutableSequence
from math import isqrt

class SudokuArray(MutableSequence):

    def __init__(self, size=9, init_value=None):
        self.size = size
        self.array = [[init_value for _ in range(self.size)] for _ in range(self.size)]

    def check(self, row_number, column_number, number):
        if (number in self.get_row_values(row_number) or
                  number in self.get_column_values(column_number) or
                  number in self.get_nonet_values(row_number, column_number)):
            raise ExistentNumberError("Existent number in row, column or nonet",
                                      number, row_number, column_number)

    def __len__(self):
        return self.size * self.size

    def __getitem__(self, coordinates): 
        return self.array[coordinates[0]][coordinates[1]]

    def __delitem__(self, coordinates): 
        del self.array[coordinates[0]][coordinates[1]]

    def __setitem__(self, coordinates, number):
        self.check(coordinates[0], coordinates[1], number)
        self.array[coordinates[0]][coordinates[1]] = number

    def insert(self, coordinates, number):
        self.check(coordinates[0], coordinates[1], number)
        self.array[coordinates[0]].insert(coordinates[1], number)

    def __str__(self):
        return "\n".join(" ".join(map(str, row)) for row in self.array).replace("None", ".")
                         
    def get_row_values(self, row_number):
        return self.array[row_number][:]

    def get_column_values(self, column_number):
        return [row[column_number] for row in self.array]

    def get_nonet_values(self, row_number, column_number):
        width = isqrt(self.size)
        row_number -= row_number % width
        column_number -= column_number % width
        return [val for row in self.array[row_number:row_number+width]
                    for val in row[column_number:column_number+width]]

示例用途:

sudoku = SudokuArray()
sudoku[1, 2] = 9
sudoku[2, 3] = 8
sudoku[5, 5] = 4
sudoku[4, 4] = 3
sudoku[3, 3] = 6
print(sudoku)

Python相关问答推荐

指示组内的rejected_time是否在creation_timestamp后5分钟内

在Pandas框架中截短至固定数量的列

如何使用Google Gemini API为单个提示生成多个响应?

即使在可见的情况下也不相互作用

@Property方法上的inspect.getmembers出现意外行为,引发异常

DataFrame groupby函数从列返回数组而不是值

try 在树叶 map 上应用覆盖磁贴

如何删除索引过go 的lexsort深度可能会影响性能?' &>

将输入管道传输到正在运行的Python脚本中

更改键盘按钮进入'

如何在类和classy-fastapi -fastapi- followup中使用FastAPI创建路由

django禁止直接分配到多对多集合的前端.使用user.set()

如何从pandas的rame类继承并使用filepath实例化

如何排除prefecture_related中查询集为空的实例?

Polars将相同的自定义函数应用于组中的多个列,

基于另一列的GROUP-BY聚合将列添加到Polars LazyFrame

Python日志(log)模块如何在将消息发送到父日志(log)记录器之前向消息添加类实例变量

根据Pandas中带条件的两个列的值创建新列

在电影中向西北方向对齐""

为什么在Python中00是一个有效的整数?