编写数独解算器与Python

问题描述 投票:1回答:4

这里是我的数独解算器编写Python语言,当我运行这个程序似乎有一个问题,在更新功能和解决功能。

不管多少时间,我过目四处移动代码,我似乎没有运气

谁能帮我?


import copy


def display (A):

    if A:
        for i in range (9):
            for j in range (9):
                if type (A[i][j]) == type ([]): print A[i][j][0],
                else: print A[i][j]
            print
        print
    else: print A

def has_conflict(A):

    for i in range(9):
        for j in range(9):
            for (x,y) in get_neighbors(i,j):
                if len(A[i][j])==1 and A[i][j]==A[x][y]: return True
    return False


def get_neighbors(x,y):

    neighbors = []
    for i in range(3):
        for j in range(3):
            a = 3*(x / 3)+i
            b = 3*(y / 3)+j
            if (x,y) != (a,b):
                neighbors += [(a,b)]

    for i in range(9):
        if (x,y) != (x,i) and (x,i) not in neighbors:
            neighbors += [(x,i)]
        if (x,y) != (i,y) and (i,y) not in neighbors:
            neighbors += [(i,y)]

    return neighbors



def update(A,x,y,value):

    B = copy.deepcopy(A)
    B[x][y] = [value]
    for (i,j) in get_neighbors(x,y):
        if B[i][j] == B[x][y]:
            if len(B[i][j]) > 1: B[i][j].remove(value)
            else: return [] 
    if has_conflict(B) == True: return []
    else: return B


def solve(A):

    for x in range (9):
        for y in range(9):
            if len(A[x][y]) == 1: return A[x][y]
            if len(A[x][y]) > 1:
                lst = update(A,x,y,A[x][y])
                if len(lst[x][y]) > 1: solve(lst)
                if lst == []: return []
                if len(lst[x][y]) == 1: return lst
            else: return A[x][y]    



A=[]

infile = open('puzzle1.txt','r')

for i in range(9):

        A += [[]]
        for j in range(9):
            num = int(infile.read(2))
            if num: A[i] += [[num]]
            else: A[i] += [[1,2,3,4,5,6,7,8,9]]

for i in range(9):

        for j in range(9):
            if len(A[i][j])==1: A = update(A, i, j, A[i][j][0])
            if A == []: break
        if A==[]: break

if A<>[]: A = solve(A)

display(A)

这里有一些困惑:

拼图1

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

难题2

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

拼图3

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

python sudoku
4个回答
3
投票

我会避免像“四处移动代码”。这就是所谓的"Programming by Coincidence"(见The Pragmatic Programmer)。编程这样不会让你成为更好的程序员。

相反,你应该拿出一张纸和一支铅笔,开始想事情应该如何工作。然后,阅读代码,并认真书写其实际作用。只有当你明白了,回去的计算机终端。


3
投票

如果你想稳定你的代码,然后写小测试案例对每个功能,确保它们正常工作。

在你的情况,运行一个谜,并确定哪些领域是错误的。然后猜测哪些功能可能会产生错误的输出。与输入调用它来看看它确实做到了。重复每次都发现错误。

[编辑] module unittest是你的朋友。


2
投票

我想帮助你,你可以写的实际代码的方式,所以这里是一些解释,有些伪代码。

不模仿人类演绎逻辑的数独解算器是暴力破解为主。基本上,你需要一个回溯算法。你有你的has_conflict方法,检查候选人是否是第一次看确定。然后你写的回溯算法是这样的:

Solve(s):
    Pick a candidate.
    Does it have a conflict? If yes, go back, and pick another one.
    No more empty cells? Then cool, return True.
    Have you run out of candidates? Then it cant be solved, return False.

    At this point, it seems ok. So call Solve(s) again, lets see how it works 
    out with the new candidate.
    If Solve returned false, then after all it was a bad candidate. Go
    back to picking another one.
    If Solve returned True, then you solved the sudoku!

这里的主要想法是,如果你的猜测是错误的,尽管没有在第一次看一个冲突,那么冲突将在调用树的地方更深显露出来。

原来的数独游戏只有一个解决办法。您可以将此方法扩展到不同的解决方案,通过解决不顾的返回值尝试任何候选人有他们数独游戏(但会使用这种方法很慢)。

有一个好的技巧,以找出是否一个数独有一个以上的解决方案。首先尝试解决的每一个电话的自然顺序候选人。然后试戴倒退。然后再做这两步,但这次请从数独的最后一个单元格的算法,后退操作。如果这四个解决方案是相同的,那么它只有一个解决方案。不幸的是我没有一个正式的证明,但它似乎工作的所有时间。我试图证明这一点,但我不与图形很大。


0
投票

解决数独需要一些暴力破解的方法,我没有看到那些在你的代码。

我也尝试过这样做,但最后我看到了norvig's codes,它只是工作完美。

并结束了最后学会他的代码。

© www.soinside.com 2019 - 2024. All rights reserved.