# Compute the product of the next n elements in matrix

4 views (last 30 days)

Show older comments

I would like to compute the product of the next n adjacent elements of a matrix. The number n of elements to be multiplied should be given in function's input. For example for this input I should compute the product of the 3 consecutive elements, starting from 1.

[product, ind] = max_product([1 2 2 1 3 1],3);

This gives (4,4,6,3).

Is there any practical way to do it? Now I do this using

for ii=1:(length(v)-2)

p=prod(v(ii:ii+n-1));

where v is the input vector and n is the number of elements to be multiplied.

Depending whether n is odd or even or length(v) is odd or even, I get sometimes right answer but sometimes the following error

Index exceeds matrix dimensions.

Error in max_product (line 6)

p=prod(v(ii:ii+n-1));.

Is there any correct general way to do it?

##### 6 Comments

Srishti Saha
on 11 Mar 2018

have posted an answer to the question that I used to complete my homework

### Answers (6)

Walter Roberson
on 4 Sep 2016

hint: cumprod divided by cumprod

##### 4 Comments

Walter Roberson
on 4 Sep 2016

Consider, for example, X * (X-1) * (X-2) * ... (X-N) for X a positive integer. That can be written as X! / (X-N-1)! which is prod(1:X) / prod(1:X-N-1) . Now if you wanted to vectorize this, to do a "sliding window", you could use cumprod() on the top and bottom, with appropriate sub-array extraction to get the right lengths.

You are not doing factorial, but what happens if you use a vector of values instead of 1:X ?

John D'Errico
on 4 Sep 2016

Edited: John D'Errico
on 4 Sep 2016

Of course, if the vector is long with elements that are larger than 1, expect this to overflow and turn the result into inf, then when you divide, you have inf/inf, so nans will result.

Or, if the elements are less than 1, then you will get underflows, which become zero. Then 0/0 is also NaN.

As well, even for some cases where overflow does not result, you may experience some loss of precision in the least significant bits, if the intermediate products exceed 2^53-1.

But for short vectors with reasonable numbers in them, this will work.

Matt J
on 4 Sep 2016

Edited: Matt J
on 4 Sep 2016

function prodout = max_product(A,n)

prodout = exp( conv(log(A),ones(1,n),'valid') );

if isreal(A), prodout=real(prodout); end

end

Just to be clear, this will handle input with zeros and negatives, e.g.,

>> prodout=max_product([0 2 2 1 3 -1], 3)

prodout =

0 4.0000 6.0000 -3.0000

##### 2 Comments

John D'Errico
on 4 Sep 2016

Drat. :) I was going to answer this with the log and conv solution. That is of course, the correct solution (and the one I was going to offer) as long as...

1. The elements are strictly positive. zero or negative values will cause problems with those logs.

2. You don't need an exact product of integers, since logs and exponents will yield subtle errors in the least significant bits.

+1 anyway, since this was going to be my solution.

Andrei Bobrov
on 4 Sep 2016

Edited: Andrei Bobrov
on 4 Sep 2016

[prodout, ind] = max_product(A,n)

ii = 1:numel(A);

ind = hankel(ii(1:n),ii(n:end));

prodout = prod(A(ind));

end

or just

max_product = @(A,n)prod(hankel(A(1:n),A(n:end)));

##### 0 Comments

Srishti Saha
on 11 Mar 2018

This should work. has been tested and refined:

function B = maxproduct(A,n)

% After checking that we do not have to return an empty array, we initialize a row vector % for remembering a product, home row and column, and one of four direction codes.

[r,c] = size(A);

if n>r && n>c

B = []; % cannot be solved

return

end

L = [-Inf,0,0,0]; % [product, home-row, home-col, direction]

for i=1:r

for j=1:c-n+1

L = check(A(i,j:j+n-1),[i,j,1],L); % row, right case

end

end

for i=1:r-n+1

for j=1:c

L = check(A(i:i+n-1,j),[i,j,2],L); % column, down case

end

end

for i=1:r-n+1

for j=1:c-n+1

S=A(i:i+n-1,j:j+n-1);

L = check(diag(S),[i,j,3],L); % diagonal, down case

L = check(diag(flip(S,2)),[i,j,4],L); % reverse diagonal, down case

end

end

i=L(2); j=L(3); % reconstruct coordinates

switch L(4)

case 1, B = [ones(n,1)*i,(j:j+n-1)'];

case 2, B = [(i:i+n-1)',ones(n,1)*j];

case 3, B = [(i:i+n-1)',(j:j+n-1)'];

case 4, B = [(i:i+n-1)',(j+n-1:-1:j)'];

end

end

function L = check(V,d,L)

p = prod(V);

if p>L(1) % if new product larger than any previous

L = [p,d]; % then update product, home and direction

end

end

##### 0 Comments

michio
on 4 Sep 2016

In the spirit of avoiding for-loops...

x = 1:10; n = 3 % Example

N = length(x);

index = zeros(N-n+1,n);

index(:,1) = 1:N-n+1';

index(:,2) = index(:,1) + 1;

index(:,3) = index(:,1) + 2;

prod(x(index),2)

##### 2 Comments

Walter Roberson
on 4 Sep 2016

michio
on 4 Sep 2016

Oops. You are exactly correct. The above script works as intended only when n = 3.

### See Also

### Categories

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!