Search code examples
matlabmatrixoctavediagonal

Iterate over diagonal elements of a Matrix in MatLab


I need to get the indexes of all diagonals in a matrix. The matrix can be non square.

The diag function gives the values, but I need the coords. So for instance with this: [1 2 3; 4 5 6; 7 8 9], I want [1 1; 2 2; 3;3] PLUS [2 6] and 3 because they are the upper diagonals of the matrix, and same for below i.e. [4 8] and 7. So the full list of indexes is: [1 1; 2 2; 3 3], [1 2; 2 3], [1 3], [2 1], [3 2], [3 1].

And I need this in the other diagonal direction too...

And it needs to work for matrices of any shape i.e. not just square ones, including vectors (i.e. 1xn and nx1) - but I guess I can test for these last 2 cases and treat separately.

EDIT: An example of a non square matrix is this 3x2 one:

1   2
3   4
5   6

In this case, the indexes I need are:

[1 1; 2 2]
[2 1; 3 2]
[1 2]
[3 1]

And then the same for diagonals running the other way...

I am aware of the diag function and can write a bit of code to iterate over the matrices, but I can't then see how to easily turn those values into indexes.

As for why I need this: It's an online course I'm doing in MatLab. An introduction to programming, using MatLab. I'm a reasonably experienced programmer but I'm not familiar with MatLab and I want to learn it more.

The question asks us to find the biggest product of any n numbers in any direction, i.e. rows, cols, and diagonals (both ways). And the thing is we don't return the product, we return the indexes of the elements making up this product.

I hope this provides more information.

EDIT 2: Sorry for not getting back to you guys, I've been very busy doing other things. When I first posted here, I assumed I was missing something and this would be something that took a few lines. But it's trickier than that, so the code you guys are posting will take me a little more time to go through and understand etc. But I hope to do this today and accept one as an answer. Thanks for all the replies.


Solution

  • Ok, so I coded this up myself last night. It's very long and I'm sure it can be done in better ways. I don't know MatLab well, so my solution is pretty naive. But it works.

    function indicies = maxproduct(A, n)
    
    
    function diagIndicies = getAllReverseDiagonalIndicies()
        % This function returns lists of indicies in the reverse diagonal direction (top-right to bottom-left)
        if rows == 1 
            numCells = 0;
            for j=1:length(A)
                temp = [1, j];
                numCells = numCells + 1;
                diagIndicies{numCells} = temp;
            end
            return
        end
    
        % This loop adds all diagonals down and to the right, to the end of the matrix.
        %fprintf('Diagonals down to main one are:\n');
        numCells = 0;
        for x=1:rows
            rowNum = x;
            colNum = 1;
            temp = [];
            while rowNum >= 1 && rowNum <= rows && colNum <= cols
                temp = [temp; [rowNum colNum]];
                rowNum = rowNum - 1;
                colNum = colNum + 1;
            end
            numCells = numCells + 1;
            temp = flipud(temp); % Need row major order for assignment
            %disp(temp);
            diagIndicies{numCells} = temp;
        end
    
        % Now go along bottom row
        %fprintf('Diagonals along bottom are:\n');
        for y=2:cols
            rowNum = rows;
            colNum = y;
            temp = [];
            while rowNum >= 1 && colNum <= cols
                temp = [temp; [rowNum colNum]];
                rowNum = rowNum - 1;
                colNum = colNum + 1;
            end
            numCells = numCells + 1;
            temp = flipud(temp); % Need row major order for assignment
            %disp(temp);
            diagIndicies{numCells} = temp;
        end                
    
    end
    
    function diagIndicies = getAllDiagonalIndicies()
        % This function returns lists of indicies in the main diagonal direction (top-left to bottom-right)
        if rows == 1 
            numCells = 0;
            for j=1:length(A)
                temp = [1, j];
                numCells = numCells + 1;
                diagIndicies{numCells} = temp;
            end
            return
        end
    
         % This loop adds all diagonals down and to the left, to the lhs of the matrix.
        %fprintf('Diagonals down to main one are:\n');
        numCells = 0;
        for x=1:rows
            rowNum = x;
            colNum = cols;
            temp = [];
            while rowNum >= 1 && rowNum <= rows && colNum >= 1
                temp = [temp; [rowNum colNum]];
                rowNum = rowNum - 1;
                colNum = colNum - 1;
            end
            numCells = numCells + 1;
            temp = flipud(temp); % Need row major order for assignment
            %disp(temp);
            diagIndicies{numCells} = temp;
        end
    
        % Now go along bottom row...
        %fprintf('Diagonals along bottom are:\n');
        for y=cols-1:-1:1
            rowNum = rows;
            colNum = y;
            temp = [];
            while rowNum >= 1 && colNum >= 1
                temp = [temp; [rowNum colNum]];
                rowNum = rowNum - 1;
                colNum = colNum - 1;
            end
            numCells = numCells + 1;
            temp = flipud(temp); % Need row major order for assignment
            %disp(temp);
            diagIndicies{numCells} = temp;
        end
    
     end
    
    
     % Main function starts here.
    
    [rows, cols] = size(A);
    
    theMaxProduct = -10000000;
    indicies = [];
    
    if isscalar(A)
        if A == 1 && n == 1
            indicies = [1,1];
            return;
        else
            return;
        end
    end
    
    
    
    % Find max product in each row of A
    for i=1:rows
        for j=1:cols-n+1
            theProduct = 1;
            for k=j:j+n-1
                theProduct = theProduct * A(i, k);
            end
            if theProduct > theMaxProduct
                theMaxProduct = theProduct;
                indicies = [];
                for k=j:j+n-1
                    indicies = [indicies; [i, k]];
                end
    
            end
        end
    end
    fprintf('theMaxProduct after examining rows = %15.15f\n', theMaxProduct);
    
    % Find max product in each column of A
    for i=1:cols
        for j=1:rows-n+1
            theProduct = 1;
            for k=j:j+n-1
                theProduct = theProduct * A(k, i);
            end
            if theProduct > theMaxProduct
                theMaxProduct = theProduct;
                indicies = [];
                for k=j:j+n-1
                    indicies = [indicies; [k, i]];
                end
    
            end
        end
    end
    fprintf('theMaxProduct after examining cols = %15.15f\n', theMaxProduct);
    
    
    
    % Find max product along reverse diagonals of A
    diagIndicies = getAllReverseDiagonalIndicies();
    %disp(diagIndicies);
    for i=1: length(diagIndicies)
        [numIndicies, ~] = size(diagIndicies{i});
        for j=1:numIndicies-n+1
            theProduct = 1;
            for k=j:j+n-1
                theProduct = theProduct * A(diagIndicies{i}(k, 1), diagIndicies{i}(k, 2));
            end
            if theProduct > theMaxProduct
                theMaxProduct = theProduct;
                indicies = [];
                for k=j:j+n-1
                    indicies = [indicies; [diagIndicies{i}(k, 1), diagIndicies{i}(k, 2)]];
                end
    
            end
        end
    end
    fprintf('theMaxProduct after examining reverse diag = %15.15f\n', theMaxProduct);
    
    
    % Find max product along diagonals of A
    diagIndicies = getAllDiagonalIndicies();
    %disp(diagIndicies);
    for i=1: length(diagIndicies)
        [numIndicies, ~] = size(diagIndicies{i});
        for j=1:numIndicies-n+1
            theProduct = 1;
            for k=j:j+n-1
                theProduct = theProduct * A(diagIndicies{i}(k, 1), diagIndicies{i}(k, 2));
            end
            if theProduct > theMaxProduct
                theMaxProduct = theProduct;
                indicies = [];
                for k=j:j+n-1
                    indicies = [indicies; [diagIndicies{i}(k, 1), diagIndicies{i}(k, 2)]];
                end
    
            end
        end
    end
    fprintf('theMaxProduct after examining main diag = %15.15f\n', theMaxProduct);
    

    end