Reputation: 173
I have a task to find the maximum product of elements in a matrix. The input arguments are the matrix and the scalar n that tells me how many elements to multiply. If n=2, then I should multiply two by two. The maximum product can lie either in rows, or in columns on in diagonal. For example in this case A's elements were multiplied 2 by 2 along rows (B) and columns (C).
A =
8 1 6
3 5 7
4 9 2
B =
8.0000 6.0000
15.0000 35.0000
36.0000 18.0000
C =
24.0000 5.0000 42.0000
12.0000 45.0000 14.0000
I do it using the loop
c=[]
for ii = 1:(length(A)-n+1)
p = prod(A(:,ii:ii+n-1));
c=[c p];
end
or
for i=1:size(A,2)
B(i,:)=real(exp(conv(log(A(i,:)),ones(1,n),'valid')));
C(:,i)=real(exp(conv(log(A(:,i)),ones(1,n),'valid')));
end
In both cases I receive the product but when it comes to getting the maximum among that products, (in my case that is the product of A(2,2)*A(3,2)=45) I cannot find the indices of original matrix elements that formed that product, i.e. (2,2) and (3,2).
Any help will be appreciated.
Upvotes: 1
Views: 199
Reputation: 460
The information can be worked out from knowing where, in B or C, the maximum value occurs. This is returned by the max function as a second argument, albeit in index form. I've tried out your code for producing B and C, and it doesn't seem to produce what you've got, HOWEVER, assuming that you've got some way of producing B and C as in the first part of your question, the following code will return (r1,c1) and (r2,c2) the reference to the two multiplicands (assuming that there is only one maximum - you really do need to check for this):
[maxB,IB]=max(B(:));
[maxC,IC]=max(C(:));
if (maxB>maxC)
[r1,c1]=ind2sub(size(B),IB);
r2=r1; c2=c1+n-1;
else
[r1,c1]=ind2sub(size(C),IC);
r2=r1+n-1; c2=c1;
end
I'm not quite sure whether n is a distance, in which case:
B=A(:,1:end-n+1).*A(:,n:end);
C=A(1:end-n+1,:).*A(n:end,:);
or whether you mean to take the product of all terms within n of the starting point. Either way, the maximum can be found using the above code.
Upvotes: 1
Reputation: 523
Given inputs A and n, and assuming you don't care which output you give in case of a tie,
%Setup
[r, c] = size(A)
if r <= n
maxProd = prod(A(1:n,1),1);
elseif c <= n
maxProd = prod(A(1,1:n),2);
else
return
end
indOut = zeros(n, 2);
dirOut = 0;
%Check verticals
for ii = 1:(r-n+1)
for jj = 1:c
testProd = prod(A(ii:ii+n-1,jj),1);
if testProd > maxProd
maxProd = testProd;
indOut(1,:) = [ii jj];
dirOut = 1;
end
end
end
%Check horizontals
for ii = 1:r
for jj = 1:(c-n+1)
testProd = prod(A(ii,jj:jj+n-1),2);
if testProd > maxProd
maxProd = testProd;
indOut(1,:) = [ii jj];
dirOut = 2;
end
end
end
%Set output
for ii = 2:n
if dirOut == 1;
indOut(1,n) = indOut(1,n-1) + 1;
else
indOut(2,n) = indOut(2,n-1) + 1;
end
end
If you do care about ties, you'll have to add additional outputs to the side of the indOut matrix
Upvotes: 1