如何解决求解数独的回溯算法
首先,感谢您花时间阅读本文。
我正在尝试创建一种回溯算法来解决特定的数独棋盘。但是,我遇到了一个问题,我考虑了很长时间但无法理解。下面是我的回溯算法:
# The puzzle itself
board = [
[0,6,8,4,0],[2,1,7],[0,3,9,7,2,[7,4],5,0]
]
# A function which prints out the board in grids
def print_board():
j = 1
for rows in board:
i = 1
for elements in rows:
if i % 3 == 0:
print(elements,"|",end=" ")
else:
print(elements,end=" ")
i += 1
if j % 3 == 0:
print("")
print("-----------------------",end="")
j += 1
print("")
# A function which searches for the coordinate [x,y] of empty Boxes (in this case if the value = 0 it is empty)
def search_empty():
empty_list = []
j = 0
for rows in board:
i = 0
for elements in rows:
if elements == 0:
empty_list.append([i,j])
i += 1
j += 1
return empty_list
# A function which takes the coordinate of an empty Box and returns all the coordinates of Boxes which fall in the same grid.
def set_grid(x,y):
if x in range(3) and y in range(3):
return [[0,1],2],[1,2]]
elif x in range(3,6) and y in range(3):
return [[3,[3,[4,[5,2]]
elif x in range(6,9) and y in range(3):
return [[6,[6,[8,2]]
elif x in range(3) and y in range(3,6):
return [[0,3],5],5]]
elif x in range(3,6) and y in range(3,6):
return [[3,5]]
elif x in range(6,9) and y in range(3,6):
return [[6,5]]
elif x in range(3) and y in range(6,9):
return [[0,6],8],8]]
elif x in range(3,6) and y in range(6,9):
return [[3,8]]
elif x in range(6,9) and y in range(6,9):
return [[6,8]]
# A function which takes 3 inputs: lower,x and y.
# lower is the starting integer to test on,so first Box defaults to 0. If say integer = 6 is the first answer to the first empty
# Box,but 1 - 9 does not satisfy the rules of Sudoku for the second Box,we backtrack to first Box and start from integer + 1
# x and y are both coordinates of the empty Box
def conditions(lower,x,y):
grid_list = set_grid(x,y)
for integers in range(lower,10):
print("Conditions running.")
grid_test = True
vertical_test = True
horizontal_test = True
# Grid test is to test if the current integer is present in the grid. If present,fails the grid test.
for i in grid_list:
[p,q] = i
if integers == board[q][p]:
grid_test = False
break
# Horizontal test is to test if the current integer is present in the same row. If present,fails the row test.
for i in board[y]:
if integers == i:
horizontal_test = False
break
# Vertical test is to test if the current integer is present in the same column. If present,fails the vertical test.
for i in range(9):
if integers == board[i][x]:
vertical_test = False
break
# If all three tests are satisfied and passed,the function returns True and the integer which satisfies all 3 rules.
if grid_test and horizontal_test and vertical_test:
print("Condition satisfied.")
return True,integers
print("Condition unsatisfied.")
return False,0
# This is where the backtracking begins.
def trials():
n = 0
a = 1
# A list which records all the "correct at that time" integers from prevIoUs empty Boxes. New "correct" integers are appended.
history = []
# Creates a static list of coordinates of empty Boxes.
empty_list = search_empty()
while True:
## This line is to debug
print(history)
# p has value of True or False,and q has value of the correct integer if True,0 if False
[p,q] = conditions(a,empty_list[n][0],empty_list[n][1])
if not p:
# If p is false,we backtrack by shifting to the last empty Box.
n -= 1
# a is the 'lower' input for conditions() function.
a = history[n] + 1
[x,y] = empty_list[n]
# Since the 'correct' answer of prevIoUs Box is not correct anymore,we are replacing it back with 0 (erasing it).
board[y][x] = 0
## This line is to debug.
print("a:",a,"old a:",history[n])
# Removing the old 'correct' answer from the history list.
history.remove(history[n])
else:
# If p is True,the 'correct' integer gets appended to the list.
history.append(q)
[x,y] = empty_list[n]
# The correct answer is replacing the 0 (writing it on the empty Box).
board[y][x] = q
# n increments by 1 to proceed to the next empty Box.
n += 1
# When we run through the entire list of empty Boxes,we break this loop.
if n == len(empty_list) - 1:
print("Done!")
break
print_board()
trials()
print_board()
但是,当我跑的时候,我会看到以下内容:
0 0 6 | 8 4 0 | 0 0 0 |
2 0 1 | 0 6 0 | 0 0 7 |
0 3 9 | 0 0 0 | 0 1 0 |
-----------------------
0 0 0 | 0 9 8 | 3 0 0 |
0 6 0 | 0 0 0 | 0 9 0 |
0 0 7 | 3 2 0 | 0 0 0 |
-----------------------
0 4 0 | 0 0 0 | 1 3 0 |
7 0 0 | 0 1 0 | 8 0 4 |
0 0 0 | 0 3 5 | 7 0 0 |
-----------------------
[]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition satisfied.
[5]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition satisfied.
[5,7]
Conditions running.
Condition satisfied.
[5,1]
Conditions running.
Conditions running.
Condition satisfied.
[5,2]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition unsatisifed
a: 3 old a: 2
[5,1]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition satisfied.
[5,9]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition unsatisifed
a: 10 old a: 9
[5,1]
Condition unsatisifed
a: 2 old a: 1
[5,2]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition satisfied.
[5,9]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition unsatisifed
a: 10 old a: 9
[5,2]
Condition unsatisifed
a: 3 old a: 2
[5,3]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition satisfied.
[5,3]
Condition unsatisifed
a: 4 old a: 3
[5,7]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition satisfied.
[5,9]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition unsatisifed
a: 10 old a: 9
[5,7]
Condition unsatisifed
a: 8 old a: 7
[5]
Conditions running.
Conditions running.
Condition unsatisifed
a: 6 old a: 5
[]
Conditions running.
Conditions running.
Conditions running.
Conditions running.
Condition unsatisifed
我正在努力理解 [5,7] 如何在没有执行任何条件检查的情况下跳转到 [5](从 [5] 和 [5,7] 之间没有“条件运行”可以看出这一点。这让我相信这是算法失败的主要原因。
非常感谢任何帮助。这是我正在从事的第一个实际项目,所以如果有任何初学者错误,我全神贯注:)
解决方法
只是一些旁注,数独问题的纯回溯通常会导致大量的执行时间。
您的问题是在找到好的解决方案时您从不重置 a
。一种解决方案可能是在 while 循环的 a=1
末尾添加 else
。此外,您使用 history.remove(history[n])
删除 history
中等于 history[n]
的第一项,从而导致一些错误。您应该将其替换为 del
。这是更正的循环:
while True:
## This line is to debug
# p has value of True or False,and q has value of the correct integer if True,0 if False
[p,q] = conditions(a,empty_list[n][0],empty_list[n][1])
if not p:
# Removing the old 'correct' answer from the history list.
del(history[n])
# If p is false,we backtrack by shifting to the last empty box.
n -= 1
# a is the 'lower' input for conditions() function.
a = history[n] + 1
history[n]+=1
board[y][x] = 0
[x,y] = empty_list[n]
# Since the 'correct' answer of previous box is not correct anymore,we are replacing it back with 0 (erasing it).
## This line is to debug.
else:
# If p is True,the 'correct' integer gets appended to the list.
history[n]=q
history.append(0)
[x,y] = empty_list[n]
# The correct answer is replacing the 0 (writing it on the empty box).
board[y][x] = q
n += 1
# n increments by 1 to proceed to the next empty box.
a=1
# When we run through the entire list of empty boxes,we break this loop.
if n == len(empty_list):
print("Done!")
break
这导致输出:
0 0 6 | 8 4 0 | 0 0 0 |
2 0 1 | 0 6 0 | 0 0 7 |
0 3 9 | 0 0 0 | 0 1 0 |
-----------------------
0 0 0 | 0 9 8 | 3 0 0 |
0 6 0 | 0 0 0 | 0 9 0 |
0 0 7 | 3 2 0 | 0 0 0 |
-----------------------
0 4 0 | 0 0 0 | 1 3 0 |
7 0 0 | 0 1 0 | 8 0 4 |
0 0 0 | 0 3 5 | 7 0 0 |
-----------------------
Done!
5 7 6 | 8 4 1 | 9 2 3 |
2 8 1 | 9 6 3 | 5 4 7 |
4 3 9 | 2 5 7 | 6 1 8 |
-----------------------
1 2 4 | 5 9 8 | 3 7 6 |
3 6 8 | 1 7 4 | 2 9 5 |
9 5 7 | 3 2 6 | 4 8 1 |
-----------------------
6 4 5 | 7 8 9 | 1 3 2 |
7 9 3 | 6 1 2 | 8 5 4 |
8 1 2 | 4 3 5 | 7 6 9 |
-----------------------
正确答案是什么。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。