How can I fix my function which is designed to solve determinants? - python

The function can accurately compute 1x1, 2x2, and 3x3 determinants, but it gives wrong values for higher order determinants. I'm thinking there's a problem with the part in the function where I call the function (recursion) to solve lower order determinants as part of the solution.
I suspect it has something to do with variable locality, but I'm not sure why that would be an issue because I thought locality was automatic.
This is Python 2 by the way.
Code:
def is_Det(matrix):
isdet = True
if not isinstance(matrix,list): # Is this actually a list?
isdet = False
for i in matrix:
if isinstance(i,list): # Things in matrix are lists?
if len(i) == len(matrix): # Square shape?
for j in i: # All numbers?
try:
j = float(j)
except ValueError:
isdet = False
else:
isdet = False
else:
isdet = False
return isdet
def det_Disp(matrix):
if is_Det(matrix):
pass
else:
print "Error: Input not a determinant, cannot display"
def det_Eval(matrix):
print matrix
except StandardError:
print "No such value"
if is_Det(matrix):
if len(matrix) == 1: # 1x1 determinant
print matrix[0][0]
return matrix[0][0]
elif len(matrix) == 2: # 2x2 determinant
print matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
else:
longdet = matrix # Expands higher-order determinant
for row1 in longdet:
for col1 in range(0,len(matrix)-1):
row1.append(row1[col1])
value = 0
for col2 in range(0,len(matrix)): # Recurse determinant value
subdet = []
for row2 in range(1,len(matrix)):
subsubdet = []
for col3 in range(col2+1,col2+len(matrix)):
subsubdet.append(longdet[row2][col3])
'''print "Subsubdet:",
print subsubdet #***************************'''
subdet.append(subsubdet)
'''# print "Subdet",
print "Subdet:",
print subdet #***************************'''
value += longdet[0][col2] * det_Eval(subdet)
##########print value
'''#print longdet[1][col2],
#print det_Eval(subdet),
#print value
# print longdet'''
return value
else:
print "Error: Input not a determinant, cannot evaluate"
#print det_Eval([[2,3],[4,9]])
#print det_Eval([[6,1,8],[9,9,9],[9,7,4]])
print det_Eval([[8,9,2,3],[4,6,1,8],[9,9,9,9],[1,9,7,4]])

In this line dealing with minors:
value += longdet[0][col2] * det_Eval(subdet)
you don't take sign into account - sign depends on parity of index of the first line element (col2)

Related

Efficient way to find if a Matrix is Sub-Matrix of another one?

Given two matrices A and B.
Is there efficient or more pythonic way to find if B is a Sub-Matrix of A?
The code below is worked but I got a Time limit exceeded when the matrix is so big!
Note: The matrix data structure is represented as an array of strings.
[Input]
A=[
'7283455864',
'6731158619',
'8988242643',
'3830589324',
'2229505813',
'5633845374',
'6473530293',
'7053106601',
'0834282956',
'4607924137']
B=[
'9505',
'3845',
'3530']
[Code]
def gridSearch(G, P):
# Write your code here
n=len(G) # Matrix G row number
m=len(G[0]) # Matrix G col number
r=len(P) # Matrix P row number
c=len(P[0]) # Matrix P col number
found='NO'
for i in range(n-r+1):
for j in range(m-c+1):
start_row=i
end_row=i+r
start_col=j
end_col=j+c
sub=[]
if G[start_row][start_col]==P[0][0]:
sub=[x[start_col:end_col] for x in G[start_row:end_row] ]
if (sub==P):
found='YES'
#print(i,j)
return(found)
[Expected Output]
YES
Rather than search on a letter by letter basis as you seem to be doing with your code, I would utilize the ability to search for strings within another string as follows:
def gridSearch(G, P):
g_sze = len(G)
p_sze = len(P)
p_ptr = 0
for g_ptr, g_row in enumerate(G):
if P[p_ptr] in g_row:
p_ptr += 1
if p_ptr == p_sze:
return True
else:
p_ptr = 0
if g_sze - g_ptr < p_sze-p_ptr:
return False
return False
The above code makes use of two efficiency approaches, first it searches the arrays by rows and secondly it stops searching rows when the ability to match the remaining rows of the smaller array is no longer possible
Given your second example, here is an approach which uses the string search approach and requires column alignment.
def gridSearch2(G, P):
g_sze = len(G)
p_sze = len(P)
candidates = []
# First scan for possible start postions
for row in range(g_sze - p_sze + 1):
idx = 0
while idx < g_sze - p_sze:
ptr = G[row].find(P[0], idx)
if ptr < 0:
break
candidates.append((row, ptr+idx))
idx = idx + ptr + 1
# test each possible start postion for matching follow on rows
while len(candidates) > 0:
row, idx = candidates.pop(0);
rslt = True
for pr in range(1, p_sze):
if G[row + pr].find(P[pr], idx) != idx:
rslt = False
break
if rslt:
return True
return False

Can someone help me replace the **for loop** to **while loop** I'm struggling to figure it out?

Can someone help me replace the for loop to while loop I'm struggling to figure it out?
The question specifically asks us not to use for loop. That's why I need to replace it with the while loop
I have listed below:
my code
Sample testing of the input and the output
the conditions we have to follow:
def matrix_equal(matrix1, matrix2):
"""
-------------------------------------------------------
Compares two matrices to see if they are equal - i.e. have the
same contents in the same locations.
Use: equal = matrix_equal(matrix1, matrix2)
-------------------------------------------------------
Parameters:
matrix1 - the first matrix (2D list of ?)
matrix2 - the second matrix (2D list of ?)
Returns:
equal - True if matrix1 and matrix2 are equal,
False otherwise (boolean)
------------------------------------------------------
"""
equal = True
if((len(matrix1) != len(matrix2)) or (len(matrix1[0]) != len(matrix2[0]))):
equal = False
for x in range(len(matrix1)):
if(equal == False):
break
for y in range(len(matrix1[0])):
num1 = matrix1[x][y]
num2 = matrix2[x][y]
if(num1 != num2):
equal = False
break
return equal
Sample testing:
First matrix:
0 1 2
0 c a t
1 d o g
2 b i g
Second matrix:
0 1 2
0 c a t
1 d o g
2 b i g
Equal matrices: True
The conditions we have to follow:
1. should not call input in the function
2. should not call print in the function
3. should not have multiple returns
This should solve your problem, this is a solution using while loop :
def matrix_equal(mat1,mat2):
equal = True
if(len(mat1[0]) == len(mat2[0]) and len(mat1) == len(mat2)):
i = 0
n = len(mat1[0])
m = len(mat1)
while(i < m):
j = 0
while(j < n):
if(mat1[i][j] != mat2[i][j]):
equal = False
break
j+=1
if(equal==False):
break
i+=1
else:
equal = False
return equal
Change
for x in range(len(matrix1)):
to
x = 0
while x < len(matrix1):
x += 1
Cheers!
You can transform :
for i in range(mat.shape[0]):
{do stuff...}
into
i = 0
while i < mat.shape[0]:
{do stuff...}
# increment i with 1
i += 1
so here you would get :
def mat_eq_while(matrix1, matrix2):
i = 0
j = 0
equal = True
if(not (mat1.shape == mat2.shape) ):
equal = False
while i < mat1.shape[0]:
if(equal == False):
break
while j < mat1.shape[1]:
num1 = matrix1[i, j]
num2 = matrix2[i, j]
if(num1 != num2):
equal = False
break
j += 1
i += 1
return equal
test it with
import numpy as np
mat1 = np.matrix(range(9)).reshape(3,3)
mat2 = np.matrix(range(1, 10)).reshape(3,3)
print( mat_eq_while(mat1, mat1) )
print( mat_eq_while(mat1, mat2) )

Can I check if an element exists within a nested list at a specific index?

Someone recently posted this question. Before I could respond with my answer, the post was removed. The request was to check for the existence of an integer value within a 4x4 array without defining a function.
Given a value and a column the answer would be:
if sum([True for x in array2d if x[col] == value]) > 0:
#!/usr/bin/env python3
import random
if __name__ == "__main__":
# initialize a 4 x 4 array with integers
array2d = [[x for x in range(0,4)] for i in range(0,4)]
# shuffle the numbers for variability
for i in range(1,4):
random.shuffle(array2d[i])
# print each row for validation
for row in array2d:
print(row)
# pick colum 2 to check for value 2
col = 2
value = 2
if sum([True for x in array2d if x[col] == value]) > 0:
print("value {0} found in colum {0}".format(value, col))
else:
print("value {0} missing in colum {0}".format(value, col))
# pick colum 3 to check for value 2
col = 2
value = 20 # This vauel will always be missing.
if any([True for x in array2d if x[col] == value]) > 0:
print("value {0} found in colum {0}".format(value, col))
else:
print("value {0} missing in colum {0}".format(value, col))
your going to want to traverse the 2 dimensional array with nested for loops.
first initialize a boolean isFound to false. and ints i and j to -1. use iterators i and j to represent the current row and current column being search. check if the waldo that u are searching for is in the given array's column i row j. if so u have found waldo, so record the location by storing a tuple with i and j, and change your isFound boolean to true. if not increment the iterators and keep traversing the array.
waldo = #value being searched
array[][] = #array being traversed
isFound = False
i = -1
j = -1
for i in range(4):
for j in range(4):
if array[i][j] == waldo:
isFound = True
location = (i, j)
print('found waldo? ', isFound)
print('location: array[', i, '][', j, ']')
output (examples):
found waldo? true
location: array[3][2]
found waldo? false
location: array[-1][-1]

Python Greedy Sum

I am currently working on this code and the only thing that seems to work is the "no solution." Also it seems that the code has an infinite loop and I can't seem to figure out how to solve it. If someone could point out my mistake it would be appreciated.
def greedySum(L, s):
""" input: s, positive integer, what the sum should add up to
L, list of unique positive integers sorted in descending order
Use the greedy approach where you find the largest multiplier for
the largest value in L then for the second largest, and so on to
solve the equation s = L[0]*m_0 + L[1]*m_1 + ... + L[n-1]*m_(n-1)
return: the sum of the multipliers or "no solution" if greedy approach does
not yield a set of multipliers such that the equation sums to 's'
"""
if len(L) == 0:
return "no solution"
sum_total = (0, ())
elif L[0] > k:
sum_total = greed(L[1:], k)
else:
no_number = L[0]
value_included, take = greed(L, k - L[0])
value_included += 1
no_value, no_take = greed(L[1:], k)
if k >= 0:
sum_total = (value_included, take + (no_number,))
else:
sum_total = (value_included, take + (no_number,))
return sum_total
sum_multiplier = greed(L, s)
return "no solution" if sum(sum_multiplier[1]) != s else sum_multiplier[0]
Second method:
def greedySum(L, s):
answer = []
try:
while (s >= L[0]):
total = s// L[0]
s -= (total * L[0])
answer.append(total)
L = L[1:]
return(str(answer)[1:-1])
except:
return("no solution")
Here is something that works:
def greedySum(L, s):
multiplier_sum = 0
for l in L:
(quot,rem) = divmod(s,l) # see how many 'l's you can fit in 's'
multiplier_sum += quot # add that number to the multiplier_sum
s = rem # update the remaining amount
# If at the end and s is 0, return the multiplier_sum
# Otherwise, signal that there is no solution
return multiplier_sum if s == 0 else "no solution"
I would offer more help on what is wrong with your code, but that is for the moment a moving target - you keep changing it!
>>> greedySum([4,2],8)
2
>>> greedySum([4,2],9)
'no solution'
>>> greedySum([4,2,1],9)
3

Python code efficiency

This program tests if a matrix is an identity matrix or not.
I have pasted my code beneath, and would like to know ways in which I can optimize the efficiency of this code. Also I am new to python programming, are there some built in functions that can solve the purpose too?
def is_identity_matrix(test):
if (test == []):
return False
i = 0
while (i < len(test)):
if (len(test[i]) == len(test)):
j = 0
while(j < len(test[i])):
if (j != i):
if(test[i][j] != 0):
return False
else:
if(test[i][j] != 1):
return False
if(j == (len(test[i]) - 1)):
break
j += 1
if(i == (len(test) - 1)):
break
i += 1
else:
return False
if(i == j and i == (len(test) - 1)):
return True
# Test Cases:
matrix1 = [[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[0,0,0,1]]
print is_identity_matrix(matrix1)
#>>>True
matrix2 = [[1,0,0],
[0,1,0],
[0,0,0]]
print is_identity_matrix(matrix2)
#>>>False
matrix3 = [[2,0,0],
[0,2,0],
[0,0,2]]
print is_identity_matrix(matrix3)
#>>>False
matrix4 = [[1,0,0,0],
[0,1,1,0],
[0,0,0,1]]
print is_identity_matrix(matrix4)
#>>>False
matrix5 = [[1,0,0,0,0,0,0,0,0]]
print is_identity_matrix(matrix5)
#>>>False
matrix6 = [[1,0,0,0],
[0,1,0,2],
[0,0,1,0],
[0,0,0,1]]
print is_identity_matrix(matrix6)
#>>>False
def is_identity_matrix(listoflist):
return all(val == (x == y)
for y, row in enumerate(listoflist)
for x, val in enumerate(row))
(though, this does not check if the matrix is square, and it returns True for an empty list)
Explanation: Inside all we have a generator expression with nested loops where val loops over each value in the matrix. x == y evaluates to True on the diagonal and False elsewhere. In Python, True == 1 and False == 0, so you can compare val == (x == y). The parentheses are important:
val == x == y would be a chained comparison equivalent to val == x and x == y
I'd use numpy:
(np.array(matrix1) == np.identity(len(matrix1))).all()
Of course, it'd be better if you were storing matrix1 as a numpy array in the first place to avoid the conversion.
Multiply by the all ones vector and check that the result is the same
Check the size of your matrix, make sure it is n x n, then create an actual identity matrix using np.identity(n), then compare your matrix with the new one you created.
def is_identity_matrix(test):
if not test : return False
le = len(test[0])
for i,x in enumerate(test):
if len(x) == le:
if any(y!=1 if j==i else y!=0 for j,y in enumerate(x)):
return False
else:
return False
return True if len(test) == le else False
If speed is important you should probably look at Numpy, but in a situation where you can't use it or perhaps it isn't worth it to have the matrix as a Numpy array you could also use the following:
def is_identity(mat):
for i, row in enumerate(mat):
if any(row[:i]) or row[i]!=1 or any(row[i+1:]):
return False
return True
About 12x faster than the code of the currently accepted answer! For a matrix of 2000x2000 at least...
The above does not check the matrix dimensions, but you can easily add something like:
n = len(matrix)
if not all(len(row) == n for row in matrix):
return False

Categories