我有一个列表列表,我正在寻找类似于组合或排列的东西,但有些条件可能导致良好的“Path”或“Dead_End”。如果是“Dead_End”,它应该索引到列表中的下一个选项。 例如:
AList = [[1, 2, 3],
[2, 0, 3],
[3, 1, 0],
[1, 0, 2]]
N = 0
Index = 0
#AList[N][Index]=1, AList[2][2]=0
我想从值AList [N] [Index]开始,它在开始时为[0] [0]因此等于1并将其分配给N.在N被赋值为1之后,我们永远不会去回到那个List和Path = [1]。
然后我会有AList [N] [Index],这是AList [1] [0]并且等于2.将它分配给N. Path.append(N)我会有Path = [1,2] ]
AList [N] [Index]接下来等于3,N = 3,Path将变为[1,2,3]
现在AList [N] [Index]等于1.这将是一个Dead_Path并不是一个好的解决方案,因为1已经在Path中,我们无法再回到它。所以我想索引到列表中的下一个选项。 Index = Index + 1.这将导致AList [N] [Index] = 0. Path = [1,2,3,0]
这是一条很好的路径,有许多好的路径和许多Dead_Ends。例如,另一个好的Path将是Path = [1,0,2,3]。
这是一个多嵌套的IF,For,While循环场景还是有一个itertools函数来测试所有的Paths和Dead_Ends?并且列表列表可能更复杂并且不均匀以创建更多Dead_Ends,例如:
BList = [[1, 4, 3],
[2, 0, 3, 4],
[3, 4, 0],
[1, 2],
[3, 2, 1, 0]]
编辑: 我无法处理所有Dead_Ends。所有的循环和索引让我感到困惑,所以我认为最好的解决方案是我使用itertools并列出所有路径组合,并允许重新访问上一个节点。然后我将使用set()函数来消除重新访问节点的列表。最后,我留下了Perfect_Paths每次点击一次。我不知道这是否是最快/最干净的,但它确实有效。代码如下:
Perfect_Path = list()
i = 0
All_Paths = list(itertools.product(*Alist))
for i in range(len(All_Paths)):
if len(set(All_Paths[i])) == len(Alist): #filter out paths that revisited a node, which means it would have same number repeated in list
Perfect_Path.append(All_Paths[i])
print ("The perfect paths are ", Perfect_Path)
编辑:我上面的代码适用于一个小的Alist,但是为了稍微大一些列表迭代所有组合,比如说10个数据节点突然变成数百万个路径。然后我必须设置()它们以消除选择。回到我的绘图板。
答案 0 :(得分:1)
一遍又一遍地阅读问题的文本,我发现了两种规则的变体,用于找到正确的答案,并且在这里提供两种规则,而不会询问哪一个是OP想到的问题。
让我们从简单的开始吧。通过矩阵元素的路径可以从一个元素跳转到任何其他元素,并且路径的唯一限制是允许的路径中没有相同的值。这使得通过矩阵的值找到所有路径变得非常容易,如下所示:
步骤1:从具有唯一值的平面集中取出所有矩阵值
步骤2:创建此集合的所有可能排列
让我们用代码演示这个变体甚至可以在一个非常大的矩阵上工作:
theMatrix = [[1, 1, 3, 2, 1, 3, 3, 3, 2, 1, 1, 3],
[1, 2, 1],
[2, 3, 3, 1, 3, 3, 2, 1, 1, 1, 3, 3, 1, 3, 3],
[3, 1, 3, 1, 2],
[2, 3, 3, 1, 3, 3, 2, 1, 1, 1, 3],
[1, 2],
[1, 2, 1],
[2, 3, 3, 1, 3, 3, 1, 1, 3, 3, 1, 3, 3],
[3, 1, 3, 1, 2],
[2, 3, 3, 1, 3, 3, 2, 1, 1, 1, 3],
[1, 2],
[2, 3, 3, 1, 3, 3, 1, 1, 3, 3, 1, 3, 3],
[3, 1, 3, 1, 2],
[2, 3, 3, 1, 3, 3, 2, 1, 1, 1, 3],
[3, 2, 1, 3, 1]]
setOnlyDifferentMatrixValues = set()
for row in range(len(theMatrix)):
for column in range(len(theMatrix[row])):
setOnlyDifferentMatrixValues.add(theMatrix[row][column])
from itertools import permutations
allPossiblePaths = permutations(setOnlyDifferentMatrixValues)
print(list(allPossiblePaths))
上面的代码输出:
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
现在是具有更多代码行的更复杂的变体。代码是必要的,因为那里有更多限制,路径只能通过邻居的矩阵元素(水平,垂直和对角线)。在这种情况下,并非所有路径都具有相同的长度和相同的元素:
def getAllValidPathsFrom(myMatrix):
# def getDictRepresentationOf(myMatrix):
dctOfMatrix = {}
for row in range(len(myMatrix)):
for column in range(len(myMatrix[row])):
currPoint = (column, row)
dctOfMatrix[currPoint] = myMatrix[row][column]
lstIndicesOfAllMatrixPoints = list(dctOfMatrix.keys())
setAllPossiblePaths = set()
from itertools import permutations
permutationsIndicesOfAllMatrixPoints = permutations(lstIndicesOfAllMatrixPoints)
cutBranchAt = ()
sizeOfCutBranch = 0
for pathCandidate in permutationsIndicesOfAllMatrixPoints:
# print(pathCandidate, type(pathCandidate))
if sizeOfCutBranch > 0:
# print( "sizeOfCutBranch > 0", cutBranchAt )
cutBranchAt = tuple(cutBranchAt)
while cutBranchAt == pathCandidate[0:sizeOfCutBranch]:
try:
pathCandidate = next(permutationsIndicesOfAllMatrixPoints)
except:
break
lstPossiblePath = []
prevIndexTuple = pathCandidate[0]
lstPossiblePath.append(prevIndexTuple)
for currIndexTuple in pathCandidate[1:]:
if (abs(currIndexTuple[0]-prevIndexTuple[0]) > 1) or (abs(currIndexTuple[1]-prevIndexTuple[1]) > 1) :
sizeOfCutBranch = len(lstPossiblePath)+1
cutBranchAt = tuple(lstPossiblePath+[currIndexTuple])
break # current path indices not allowed in path (no jumps)
else:
if dctOfMatrix[currIndexTuple] in [ dctOfMatrix[index] for index in lstPossiblePath ] :
sizeOfCutBranch = len(lstPossiblePath)+1
cutBranchAt = tuple(lstPossiblePath+[currIndexTuple])
break # only values different from all previous are allowed
else:
sizeOfCutBranch = 0
cutBranchAt = ()
lstPossiblePath.append(currIndexTuple)
prevIndexTuple = currIndexTuple
if len(lstPossiblePath) > 1 and tuple(lstPossiblePath) not in setAllPossiblePaths:
setAllPossiblePaths.add(tuple(lstPossiblePath))
return setAllPossiblePaths, dctOfMatrix
#:def getAllValidSkiingPathsFrom
theMatrix = [[3, 1, 3],
[1, 1],
[1, 2, 1, 3]]
lstAllPossiblePaths, dctOfMatrix = getAllValidPathsFrom(theMatrix)
setDifferentPossiblePaths = set(lstAllPossiblePaths)
setTpl = set()
for item in setDifferentPossiblePaths:
lstTpl = []
for element in item:
lstTpl.append(dctOfMatrix[element])
setTpl.add(tuple(lstTpl))
print(setTpl)
上面的代码在一个小矩阵上运行,因为大的矩阵会在计算上杀死它。由于小矩阵中值的特殊排列,因此可以在此证明,由于构建路径的限制性规则较多,因此不会生成所有排列。让我们比较变体1的输出和答案的变体2:
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
{(1, 2), (1, 3), (2, 1, 3), (3, 1), (2, 1), (3, 1, 2)}
因为在第二个变体中,路径必须经过相邻的矩阵元素,并不存在最长路径的所有排列,并且还包括较短的路径。