In recursive function changed COPY of argument

34 Views Asked by At

Function for calculate matrix determinant:

def determinant(matrix):
    def minor(mat,i):
        del mat[0]
        y=[]
        for x in mat:
            del x[i]
            y.append(x)
        return y
    if len(matrix)==1:
        return matrix[0][0]
    if len(matrix)==2:
        return matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]
    det=0
    for i in range(len(matrix)):
        m=matrix.copy()
        det=det+((-1)**i)*m[0][i]*determinant(minor(m,i))
m5 = [[2,4,2],[3,1,1],[1,2,0]]
determinant(m5)

But, when function minor delete elements in her argument mat, whih is a COPY of argument matrix in matrix disappear elements too!

Solved only with this ugly construction:

def determinant(matrix):
    m=matrix.copy()
    if len(m)==1:
        return m[0][0]
    if len(m)==2:
        return m[0][0]*m[1][1]-m[0][1]*m[1][0]
    if len(m)>2:
      det=0
      for i in range(len(m)):
        z=[]
        for j in range(1,len(m),1):
          x=[]
          for k in range(len(m)):
            if k!=i:
              x.append(m[j][k])
          z.append(x)   
        det=det+((-1)**i)*m[0][i]*determinant(z)
      return det
1

There are 1 best solutions below

0
Mark Tolonen On

list.copy() is a shallow copy. Use copy.deepcopy() if you want a copy of the sublists as well:

import copy

def determinant(matrix):
    def minor(mat,i):
        y = copy.deepcopy(mat)
        del y[0]
        for x in y:
            del x[i]
        return y
    if len(matrix) == 1:
        return matrix[0][0]
    if len(matrix) == 2:
        return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
    det=0
    for i in range(len(matrix)):
        det += (-1)**i * matrix[0][i] * determinant(minor(matrix,i))
    return det

m5 = [[2,4,2],[3,1,1],[1,2,0]]
print(determinant(m5))
other = [[2,4,2,3],[2,8,2,1],[1,2,2,4],[4,3,6,4]]
print(determinant(other))

#verify
import numpy as np
print(np.linalg.det(m5))
print(np.linalg.det(other))

Output:

10
-76
10.000000000000002
-76.0