我试图用Python解决以下问题:
但是我被困在生成一个有效的表。我希望程序显示一个有效的矩阵,但为了让程序继续而不打印None
,我必须为没有可能的正方形分配7
。应该修复什么?
到目前为止我的代码:
from pprint import pprint
import sys
import random
sys.setrecursionlimit(10000)
def getPossiblesForSquare(sqx,sqy,matrix):
'''Gets the possible entries of matrix[sqy][sqx].
Assumes it equals 0.'''
assert matrix[sqy][sqx]==0
# get the row that it is on
rowon=matrix[sqy]
# columns are a little trickier
colon=[matrix[row][sqx] for row in range(5)]
# find the possibilities!
possibles=list(range(1,7))
for item in list(set(rowon+colon)): # remove duplicates
if not (item == 0) and (item in possibles):
del possibles[possibles.index(item)]
random.shuffle(possibles)
return possibles
def getPossiblesForMatrix(matrix):
'''Gets all the possible squares for a matrix.'''
possiblesdict={}
for y in range(6):
for x in range(6):
if matrix[y][x]==0:
possiblesdict[(y,x)]=getPossiblesForSquare(x,y,MATRIX)
return possiblesdict
def flattenList(matrix):
result=[]
for i in matrix:
if not isinstance(i,list):
result+=[i]
else:
result+=flattenList(i)
return result
def getPossibleMatrix(startMatrix, iteration=0, yon=1, prevZeroInd=None):
if 0 not in flattenList(startMatrix):
print('RESULT:\n\n')
return startMatrix
else:
# find&fill in the first blank one
ind=flattenList(startMatrix).index(0)
y=ind//6
x=ind%6
if (x,y)==prevZeroInd:
startMatrix[y][x]=7
else:
possibles=getPossiblesForSquare(x,y,startMatrix)
if len(possibles)==0:
startMatrix[y][x]=7
else:
startMatrix[y][x]=possibles[0]
if iteration <= 6:
return getPossibleMatrix(startMatrix, iteration+1, yon, (x,y)) # <<BUG
else:
if yon!=4:
return getPossibleMatrix(startMatrix, 0, yon+1, (x,y))
MATRIX=[[1,2,3,4,5,6],
[2,0,0,0,0,5],
[3,0,0,0,0,4],
[4,0,0,0,0,3],
[5,0,0,0,0,2],
[6,5,4,3,2,1]]
result=getPossibleMatrix(MATRIX)
pprint(result)
答案 0 :(得分:3)
基本上你的脚本在这里遇到问题:
for item in list(set(rowon + colon)): # remove duplicates
if not (item == 0) and (item in possibles):
del possibles[possibles.index(item)]
[1 to 6]
,if条件被评估为true(如果输出矩阵,您将看到正在创建的set()
包含所有元素),所以你总是返回零,重新检查值,返回零ad infinitum。 如果您正在寻找强制解决此问题的解决方案,您可能需要更新sqx
和sqy
,以便在可能为空时转到其他单元格。
我找到的另一个小错误是:
# you are checking values 1-5 and not 1-6!
possibles = list(range(1, 6)) # should be range(7) [exclusive range]
当然,存在解决此问题的不同方法。
阅读本文,了解如何解决此问题的一般替代视图。如果您不想看到可能的解决方案,请跳过&#39;代码&#39;一部分。
解决方案矩阵(可能的一个)有这种形式(除非我犯了一个可怕的错误):
MATRIX = [[1, 2, 3, 4, 5, 6],
[2, 3, 6, 1, 4, 5],
[3, 1, 5, 2, 6, 4],
[4, 6, 2, 5, 1, 3],
[5, 4, 1, 6, 3, 2],
[6, 5, 4, 3, 2, 1]]
逻辑如下:
您必须观察矩阵中存在的对称性。具体来说,每一行和每一列都会显示“翻转和反转”字样。对称。例如,第一行和最后一行通过以下等式连接:
row[0] = REV(flip(row[n]))
同样,所有其他行(或列)都有相应的对应部分:
row[1] = REV(flip(row[n-1]))
等等。
所以,对于n=6
,这基本上归结为找到(n / 2) -1
(因为我们已经知道了第一行和最后一行!)然后翻转它们(而不是手指),将它们反转并分配它们到他们相应的行。
为了找到这些值,我们可以将矩阵视为较小矩阵的组合:
这些是矩阵的前两行(未知):
sub_matrix = [[1, 2, 3, 4, 5, 6],
[2, 0, 0, 0, 0, 5],
[3, 0, 0, 0, 0, 4],
[6, 5, 4, 3, 2, 1]]
可以通过为这两个行找到正确的值来制作另外两行。
遵守手头的限制:
在[1][1]
栏和[1][m-1]
栏中,我们不能:
2
或5
在[1][2]
和[1][m-2]
列中,我们不能:
[2, 5]
)与([3, 4]
)放在一起,这样我们就无法获得值in
[2,3,4,5]
对于内部列,我们留下了set(1-6) - set(2-5) = [1, 6]
集
因为我们得到一个正常的行和一个 单 反转和翻转的行,我们可以任意选择一个值并将其添加为列值。
通过使用另一个列表,我们可以跟踪使用的值并填写剩余的单元格。
注意:我没有使用numpy
。您可以,应该。 (另外,Python 2.7
)
另外,我没有使用递归(你可以尝试通过为更大的n
值找到相同的矩阵[我相信它非常适合递归函数]。
首先,为了不一直打字,你可以按如下方式创建一个n x n
矩阵:(这不是一个剧透。)
# our matrix must be n x n with n even.
n = 6
# Create n x n matrix.
head = [i for i in xrange(1, n + 1)] # contains values from 1 to n.
zeros = [0 for i in xrange(1, n-1)] # zeros
tail = [i for i in xrange(n, 0, -1)] # contains values from n to 1.
# Add head and zeros until tail.
MATRIX = [([j] + zeros + [(n+1)-j]) if j != 1 else head for j in xrange(1, n)]
# Add tail
MATRIX.append(tail)
然后,创建较小的(n/2 + 1) x n
数组:
# Split matrix and add last row.
sub_matrix = MATRIX[:(n / 2)] + [tail]
之后,一个名为sub = fill_rows(sub_matrix)
的小功能进来并负责业务:
def fill_rows(mtrx):
# length of the sub array (= 4)
sub_n = len(mtrx)
# From 1 because 0 = head
# Until sub_n -1 because the sub_n - 1 is = tail (remember, range is exclusive)
for current_row in xrange(1, sub_n - 1):
print "Current row: " + str(current_row)
# -- it gets messy here --
# get values of inner columns and filter out the zeros (matrix[row][n / 2] == 0 evaluates to False)
col_vals_1 = [mtrx[row][n / 2] for row in xrange(0, sub_n) if mtrx[row][(n / 2)]]
col_vals_2 = [mtrx[row][(n / 2) - 1] for row in xrange(0, sub_n) if mtrx[row][(n / 2) - 1]]
col_vals = col_vals_1 + col_vals_2
# print "Column Values = " + str(col_vals)
row_vals = [mtrx[current_row][col] for col in xrange(0, n) if mtrx[current_row][col]]
# print "Row Values = " + str(row_vals)
# Find the possible values by getting the difference of the joined set of column + row values
# with the range from (1 - 6).
possible_values = list(set(xrange(1, n + 1)) - set(row_vals + col_vals))
print "Possible acceptable values: " + str(possible_values)
# Add values to matrix (pop to remove them)
# After removing add to the list of row_values in order to check for the other columns.
mtrx[current_row][(n-1)/2] = possible_values.pop()
row_vals.append(mtrx[current_row][(n - 1) / 2])
mtrx[current_row][(n-1)/2 + 1] = possible_values.pop()
row_vals.append(mtrx[current_row][(n-1) / 2 + 1])
# New possible values for remaining columns of the current row.
possible_values = list(set(xrange(1, n + 1)) - set(row_vals))
print "Possible acceptable values: " + str(possible_values)
# Add values to the cells.
mtrx[current_row][(n - 2)] = possible_values.pop()
mtrx[current_row][1] = possible_values.pop()
# return updated sub-matrix.
return mtrx
现在唯一要做的就是拍摄这两行,翻转它们,反转它们并添加头部和尾部:
print '=' * 30 + " Out " + "=" * 30
# Remove first and last rows.
del sub[0]
sub.pop()
# reverse values in lists
temp_sub = [l[::-1] for l in sub]
# reverse lists in matrix.
temp_sub.reverse()
# Add them and Print.
pprint([head] + sub + temp_sub + [tail])
我希望这是正确的矩阵:
============================== Out ==============================
[[1, 2, 3, 4, 5, 6],
[2, 3, 6, 1, 4, 5],
[3, 1, 5, 2, 6, 4],
[4, 6, 2, 5, 1, 3],
[5, 4, 1, 6, 3, 2],
[6, 5, 4, 3, 2, 1]]
通过使用这种解决方法,手头问题的答案变得更加容易。将矩阵视为这些子矩阵的组合,您可以知道这些组合中有多少可能是可能的。
作为结束语,稍微修改它以便允许它为任意( 但是甚至 )找到这个数组是一个很好的解决方案。 )n
的数量。
答案 1 :(得分:0)
你有无限的递归。你的前三次迭代很好:你的第二行一次增加一种可能性,从200005变为214305.此时,你发现没有可能的选择。使用新的0,覆盖现有的0,然后无法回溯。其中每个都是错误:6是可能的值,并且您没有恢复代码。
这是我为追踪问题所做的改动;增加的是双星容器。当你有一个生病的程序,学习如何询问它在哪里受伤。打印功能是一种很好的工具。
def getPossibleMatrix(startMatrix, **iter=0**):
if 0 not in flattenList(startMatrix):
return startMatrix
else:
# find&fill in the first blank one
ind=flattenList(startMatrix).index(0)
y=ind//6
x=ind%6
possibles=getPossiblesForSquare(x,y,startMatrix)
if len(possibles)==0:
startMatrix[y][x]=0
**print ("No possibles; current location remains 0")**
else:
startMatrix[y][x]=possibles[0]
****print ("Added first possible")
print (startMatrix)
if iter <= 6:**
return getPossibleMatrix(startMatrix, **iter+1**) # <<BUG