根据要求发布部分实际代码,我的目的是学习和练习构建数独方块的示例编程,大部分代码已被省略,但下面的代码应该是可运行的并且代表我的问题。既然代码已经在这里,我们很高兴地采取改进建议,但主要问题仍然是如何不必要地避免loopin:
from random import shuffle
#for brevity ill omit how i got to this point
sudoku =[6,1,9,3,2,8,5,4,7,2,5,7,6,9,4,3,1,8,4,3,8,7,1,5,2,6,9,5,8,6,1,4,
3,9,7,2,3,9,1,2,8,7,6,5,4,7,4,2,9,5,6,1,8,3,None,None,None,None,
None,None,None,None,None,None,None,None,None,None,None,None,None,
None,None,None,None,None,None,None,None,None,None]
#provides args for list indexing to help satisfy sudoku sub-square rule
sq_pos = [(0, 1, 2, 9, 10, 11, 18, 19, 20),
(3, 4, 5, 12, 13, 14, 21, 22, 23),
(6, 7, 8, 15, 16, 17, 24, 25, 26),
(27, 28, 29, 36, 37, 38, 45, 46, 47),
(30, 31, 32, 39, 40, 41, 48, 49, 50),
(33, 34, 35, 42, 43, 44, 51, 52, 53),
(54, 55, 56, 63, 64, 65, 72, 73, 74),
(57, 58, 59, 66, 67, 68, 75, 76, 77),
(60, 61, 62, 69, 70, 71, 78, 79, 80)]
#this function finds allowed numbers for each column
def lastColumnsPossibilities(slist, n_of_square):
poss_col = []
print('in lastColumnsPossibilities')
for j in range(n_of_square*3, 3*n_of_square + 3):
col = []
pcol = []
for i in range(j, j + 46, 9):
col.append(slist[i])
for k in range(1,10):
if k not in col:
pcol.append(k)
poss_col.append(pcol)
return poss_col
#this function uses allowed numbers output by previous one
def lastSquareFill(slist, n_of_square, ff, fs, ft,
sf, ss, st, tf, ts, tt):
poss_col = lastColumnsPossibilities(slist, n_of_square)
plist = poss_col[0]
shuffle(plist)
slist[ff] = plist.pop()
slist[sf] = plist.pop()
slist[tf] = plist.pop()
dlist = poss_col[1]
shuffle(dlist)
slist[fs] = dlist.pop()
slist[ss] = dlist.pop()
slist[ts] = dlist.pop()
tlist = poss_col[2]
shuffle(tlist)
slist[ft] = tlist.pop()
slist[st] = tlist.pop()
slist[tt] = tlist.pop()
#this function provides condition according to sudoku rules
def checkRow(slist, rn):
row = []
for i in range(rn * 9, rn * 9 + 9):
row.append(slist[i])
if len(set(row)) == 9:
return True
else:
return False
#my actual loop is ofc longer, but instead of posting everything i
#provided list sudoku that is 2/3 filled
def testLoop(slist):
print('test')
while (checkRow(slist, 6) != True
or checkRow(slist, 7) != True
or checkRow(slist, 8) != True):
print('loop')
lastSquareFill(sudoku, 0, *sq_pos[6])
lastSquareFill(sudoku, 1, *sq_pos[7])
lastSquareFill(sudoku, 2, *sq_pos[8])
testLoop(sudoku)
我得到的输出是:
loop
in lastColumnsPossibilities
in lastColumnsPossibilities
in lastColumnsPossibilities
loop
in lastColumnsPossibilities
in lastColumnsPossibilities
in lastColumnsPossibilities #this repeats over and over
我想要的输出是:
loop
in lastColumnsPossibilities
in lastColumnsPossibilities
in lastColumnsPossibilities
loop
loop #only loop till solution is found
我原来的问题是,现在仍然是如何在不引入新的全局变量的情况下不进行无用的骑行(这是一种不好的做法,我被告知)。作为初学者,我很乐意接受任何其他建议,考虑我的代码和我的问题发布。对不起以前的不好问题,这是我的第一个...
答案 0 :(得分:1)
通过问题编辑,它确实澄清了手头的问题,所以我相信这就是你所追求的。
我修改了lastSquareFill
以取消poss_col
取消对它的调用。
def lastSquareFill(slist, n_of_square, poss_col, ff, fs, ft,
sf, ss, st, tf, ts, tt):
plist = poss_col[0]
shuffle(plist)
...
然后我将调用移到了while循环之外,创建了每个lastColumnsPossibilities
的列表,你也可以为每个调用一个变量,但我发现它更清晰。
# Variable for each
lcp0 = lastColumnsPossibilities(sudoku, 0)
lcp1 = lastColumnsPossibilities(sudoku, 1)
...
def testLoop(slist):
print('test')
# Create list of each lastColumnsPossibilities
# range(3) is used to match the 3 calls, but you will likely have 9 for sudoku
lcp = [lastColumnsPossibilities(sudoku, i) for i in range(3)]
while (checkRow(slist, 6) != True
or checkRow(slist, 7) != True
or checkRow(slist, 8) != True):
print('loop')
lastSquareFill(sudoku, 0, lcp[0], *sq_pos[6])
lastSquareFill(sudoku, 1, lcp[1], *sq_pos[7])
lastSquareFill(sudoku, 2, lcp[2], *sq_pos[8])
这会产生以下输出
test
in lastColumnsPossibilities
in lastColumnsPossibilities
in lastColumnsPossibilities
loop
loop
如果您希望它首先进入循环以避免在没有检查的情况下进行处理,那么您可以使用dict(列表仍然有效,但dict会更优化)
def lastSquareFill(slist, n_of_square, lcp, ff, fs, ft,
sf, ss, st, tf, ts, tt):
# if they don't exist create them and add to the dict
if n_of_square not in lcp:
lcp[n_of_square] = lastColumnsPossibilities(slist, n_of_square)
poss_col = lcp[n_of_square]
plist = poss_col[0]
shuffle(plist)
...
def testLoop(slist):
print('test')
lcp = {} # dict to hold all the lastColumnsPossibilities mapped to the square number
while (checkRow(slist, 6) != True
or checkRow(slist, 7) != True
or checkRow(slist, 8) != True):
print('loop')
lastSquareFill(sudoku, 0, lcp, *sq_pos[6])
lastSquareFill(sudoku, 1, lcp, *sq_pos[7])
lastSquareFill(sudoku, 2, lcp, *sq_pos[8])
然后给出
test
loop
in lastColumnsPossibilities
in lastColumnsPossibilities
in lastColumnsPossibilities
loop
<强>更新强>
在lastSquareFill
中,您需要复制列表[:]
,以便在弹出值时不会影响原始列表。
# make a copy instead
plist = poss_col[0][:]
dlist = poss_col[1][:]
tlist = poss_col[2][:]
答案 1 :(得分:0)
很难理解你的代码在做什么,因为很多内容被无用的模糊评论所取代。尽管如此 -
在您的次优&#39;解决方案,您将a
作为参数传递给b
,这样您就可以在函数中调用a
并将其返回值分配给局部变量var
。这非常低效,特别是因为您说值a
返回不会发生变化。避免全局变量的解决方案是:
def a(list, arg):
return another_list
def b(_list, arg, a_value, *args):
# Your code here #
return _list
def Main(list):
while some_function():
var=a(_list, arg)
b(_list, arg, var, *args)
b(_list, arg, var, *args)
b(_list, arg, var, *args)