Python - 2D列表的里程表样式组合

时间:2018-03-10 13:38:42

标签: python recursion matrix

我有一个N-by-N矩阵,只包含0和1,每列只能有一个' 1'在里面。对角线以下的元素必须为零(A [1] [1],A [2] [1],A [2] [2],A [3] [1],A [3] [2],A [3] [3] = 0)。例如:

A = [[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]

我需要存储此矩阵的所有组合,以维护之前给出的规则。我的想法是让第一行从所有的开始,然后移动' 1'在最后一列中一次向下一个地方,直到它到达底部。然后是倒数第二列' 1'将向下移动一个地方和最后一列' 1'将重复其周期。这将继续通过所有可能的组合。

很抱歉,如果这很难理解,但它类似于里程表,当最右边的表盘完全旋转时,第二个最右边的表盘转动一个位置。唯一的区别是在里程表中,每个刻度盘都有十个值,在这种情况下,值的数量会有所不同(由于对角线下方的值需要为零)。

因为我不知道矩阵的大小,所以我不能使用一定数量的嵌套for循环,而且我不确定如何递归地实现这个程序。我也看过itertools.product,但我不确定如何使用它来处理对角线规则。非常感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:1)

不使用递归的尝试,其中N是矩阵宽度:

import itertools

def column(index, length, size):
    res = [0]* (length-1)
    res.insert(index,1)
    return res + [0]*(size - len(res))

N = 4

l = []
for i in range(1, N+1):
    l1 = []
    for j in range(0,i):
        l1.append(column(j,i,N))
    l.append(l1)

result = [list(x) for x in [zip(*r) for r in itertools.product(*l)]]

对于每一列,它创建一个列表,列出每个可能的零序列和一个尊重条件的列表。然后它将它们组合起来以获得按列列出的所有矩阵,以便计算每个矩阵的trasposed以获得结果。希望它有所帮助。

答案 1 :(得分:0)

这是我的解决方案。 然而,这不是一个快速的解决方案。它使用搜索功能的递归实现。在每次递归时,它会探索每行的所有可能的产品值(不包括当前行的第一个元素,直到对角线值),并检查当前解是否有效。如果它到达递归的末尾,它将附加当前的矩阵解决方案。

假设它探索了n!解决方案,但因为我在解决方案不正确时中断搜索,搜索会在它到达所有可能的解决方案之前停止。

mvInsertionSort :: Ord a => Mv.IOVector a -> IO (Mv.IOVector a)
mvInsertionSort mv = do
    forM_ [1 .. Mv.length mv - 1] $ \x -> do
        pivot <- Mv.read mv x
        mvInsertionSort' [x-1, x-2 .. 0] mv pivot
    return mv

-- insertion Sort helper
mvInsertionSort' :: Ord a => [Int] -> Mv.IOVector a -> a -> IO ()
mvInsertionSort' (y:ys) mv pivot = do
    currElem <- Mv.read mv y
    if pivot < currElem
        then do 
                Mv.write mv y pivot 
                Mv.write mv (y+1) currElem 
                mvInsertionSort' ys mv pivot
        else Mv.write mv (y+1) pivot

mvInsertionSort' [] _ _ = return ()

更有效的解决方案是搜索列,而不是我现在正在进行搜索的行,因为检查正确性将需要更少的计算(您只需要检查当前列完全归结为1)

当然,搜索列需要沿着列移动唯一的