3

我目前正在用python编写一个数独求解程序,只是为了好玩。这是我目前拥有的:

#!/usr/bin/env python
"""Reads in a file formatted with nine lines each of which has nine characters
corresponding to a sudoku puzzle.  A blank is indicated by the value '0'
Eventually should output a solution to the input puzzle"""

import sys

class cell:
    value = 0
    """Value of 0 means it is undetermined"""

    def __init__(self, number):
        self.value = number
        self.possible = [2, 2, 2, 2, 2, 2, 2, 2, 2]
        """Possibility a given value can be the number. 0 is impossible, 1 is definite, 2 is maybe"""



    def selfCheck(self):
        """Checks if the cell has only one possible value, changes the value to that number"""
        if self.value == 0:
              if self.possible.count(2) == 1:
                """If there's only one possible, change the value to that number"""
                i = 1
                for item in self.possible:
                    if item == 2:
                        self.value = i
                        self.possible[i-1] = 1
                    i+=1

def checkSection(section):
    """For any solved cells in a section, marks other cells as not being that value"""
    for cell in section:
        if cell.value != 0:
            for otherCell in section:
                otherCell.possible[cell.value-1] = 0

def checkChunk(chunk):
    """Checks a chunk, the set of rows, columns, or squares, and marks any values that are impossible for cells based on that
    chunk's information"""
    for section in chunk:
        checkSection(section)

def selfCheckAll(chunk):
    for section in chunk:
        for cell in section:
            cell.selfCheck()

cellRows = [[],[],[],[],[],[],[],[],[]]
cellColumns = [[],[],[],[],[],[],[],[],[]]
cellSquares = [[],[],[],[],[],[],[],[],[]]

infile = open(sys.argv[1], 'r')
"""Reads the file specified on the command line"""

i = 0
for line in infile:
    """Reads in the values, saves them as cells in 2d arrays"""
    line = line.rstrip('\n')
    for char in line:
        row = i/9
        column = i%9
        newcell = cell(int(char))
        cellRows[row].append(newcell)
        cellColumns[column].append(newcell)
        row = (row/3)*3
        column = column/3
        square = row+column
        cellSquares[square].append(newcell)
        i+=1
i = 0
while i<50:
    checkChunk(cellRows)
    checkChunk(cellColumns)
    checkChunk(cellSquares)
    selfCheckAll(cellRows)

    i+=1

displayRow = []
for row in cellRows:
    for cell in row:
        displayRow.append(str(cell.value))

i = 0
while i < 9:
    output1 = ''.join(displayRow[9*i:9*i+3])
    output2 = ''.join(displayRow[9*i+3:9*i+6])
    output3 = ''.join(displayRow[9*i+6:9*i+9])
    print output1 + '  ' + output2 + '  ' + output3
    if i%3 == 2:
        print
    i+=1

我的问题是:

i = 0
while i<50:
    checkChunk(cellRows)
    checkChunk(cellColumns)
    checkChunk(cellSquares)
    selfCheckAll(cellRows)

    i+=1

我想运行代码,直到它检测到上一次迭代没有变化,而不是当前硬编码 50 次。这可能是因为不再有合乎逻辑的下一步(需要开始暴力破解值),或者难题已完全解决。无论哪种方式,我都需要一个我当前数据集的深层副本(比如 cellRows),以便与实际副本通过我的 checkChunk 函数时可能发生的变化进行比较。

Python中有这样的东西吗?(如果有更好的方法来检查我是否完成了,那也可以,尽管此时我更感兴趣的是是否可以进行深入比较。)

编辑 - 我尝试使用 copy.deepcopy。虽然这创建了一个很好的深层副本,但使用 '==' 检查两者之间的相等性总是返回 false。

4

6 回答 6

3

通过比较可以进行非常粗略的比较str()。当然不是最好的方法,但考虑到列表的复杂性,它可能没问题。

如果你想要更可靠的东西,你可以编写一个递归函数来处理它。

于 2013-05-28T19:41:11.857 回答
1

You can always pickle the objects up and compare them as strings. Converting them to a JSON string is probably one of the easiest ways. I suspect that there is a more resource-efficient way of doing this, but it works just fine. Here is an example:

>>> from simplejson import dumps
>>> ls1 = [1, [2, 3], [4, [5, 6]]]
>>> ls2 = [1, [2, 3], [4, [5, 6]]]
>>> dumps(ls1) == dumps(ls2)
True
>>>
于 2014-03-05T20:44:14.013 回答
1

I'm not sure comparing string representations is the way to go, but if performance is an issue I guess you can benchmark. Here's a quick attempt at an implementation of deep/recursive list comparison:

from itertools import izip

def list_compare(a, b):
    if type(a) != type(b):
        return False
    if type(a) != list:
        return a == b
    if len(a) != len(b):
        return False
    for a_, b_ in izip(a, b):
        if not list_compare(a_, b_):
            return False
    return True

It compares lists recursively and non-list items using the regular equality operator.

于 2015-01-21T12:46:00.950 回答
0

在您的情况下,这只是一个二维列表。因此将它们转换为一维字符串列表并比较它们将使代码最小。

list_of_list = [[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 4, 5, 6, 7, 8, 1], [3, 4, 5, 6, 7, 8, 1, 2], [4, 5, 6, 7, 8, 1, 2, 3], [5, 6, 7, 8, 1, 2, 3, 4], [6, 7, 8, 1, 2, 3, 4, 5], [7, 8, 1, 2, 3, 4, 5, 6], [8, 1, 2, 3, 4, 5, 6, 7]]
current_iteration = ",".join(["".join(map(str, row)) for row in list_of_list])
previous_iteration = ",".join(["".join(map(str, row)) for row in list_of_list])
if current_iteration == previous_iteration:
    return

生成字符串后,您可以以相同的方式转换比较板并以相同的方式进行比较。

但是,我建议直接将它们作为列表进行比较会更容易阅读

previous_iteration = [[1,2,3], [2,3,1], [3,1,2]]
current_iteration = [[1,2,3], [2,3,1], [3,1,2]]

if len(current_iteration) != len(previous_iteration):
# This check is not required in your case as the lengths will be same for all iterations
    return False

for index, item_list in enumerate(current_iteration):
    if item_list != previous_iteration[index]:
        return False

return True
于 2015-01-21T13:25:04.317 回答
0

如果它改变了某些东西,则添加checkChunk()selfCheckAll()返回。True/False之后,您可以编写如下代码

while True:
    changed = checkChunk(cellRows)
    changed = changed or checkChunk(cellColumns)
    changed = changed or checkChunk(cellSquares)
    changed = changed or selfCheckAll(cellRows)
    if not changed:
        break
于 2020-04-09T08:22:32.863 回答
-2

标准复制模块中提供了通用深度复制工具:您要搜索的是copy.deepcopy功能。

于 2013-05-28T19:41:20.147 回答