Search code examples
c#multidimensional-arrayimplementation

How to Transform a 2D Array In-Place Without Using an Additional Array in C#?


I’m trying to shift the elements of a 2D array to the right and down by one position without using an additional temporary array. Here’s the current implementation using a temporary array:

public static void TransformArray(int[,] matrix)
{
    int row = matrix.GetLength(0);
    int col = matrix.GetLength(1);
    
    int[,] tempMatrix = new int[row, col];
    
    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            tempMatrix[(i + 1) % row, (j + 1) % col] = matrix[i, j];
        }
    }

    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            matrix[i, j] = tempMatrix[i, j];
        }
    }
}

public static void Main(string[] args)
{
    int[,] matrix = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    TransformArray(matrix);

    // Output the transformed matrix
    for (int i = 0; i < matrix.GetLength(0); ++i)
    {
        for (int j = 0; j < matrix.GetLength(1); ++j)
        {
            Console.Write(matrix[i, j] + " ");
        }
        Console.WriteLine();
    }
}

I would like to avoid using tempMatrix and perform the transformation in-place. Is there an efficient way to do this in C#? Any suggestions or optimizations would be appreciated.


Solution

  • The operation you are doing seems to be equivalent to shifting all the rows to the right, and wrap around the values at the end, then shifting all the columns downwards, and also wrap around the values at the end.

    After you break it down like this, it is easy to write a ShiftRow and a ShiftColumn helper functions, without creating new arrays. You are just shifting one row/column after all.

    public static void TransformArray(int[,] matrix)
    {
        int row = matrix.GetLength(0);
        int col = matrix.GetLength(1);
        
        void ShiftRow(int rowIndex) {
            var last = matrix[rowIndex, col - 1];
            for (int i = col - 1 ; i > 0 ; i--) {
                matrix[rowIndex, i] = matrix[rowIndex, i - 1]; 
            }
            matrix[rowIndex, 0] = last;
        }
        
        void ShiftColumn(int colIndex) {
            var last = matrix[row - 1, colIndex];
            for (int i = row - 1 ; i > 0 ; i--) {
                matrix[i, colIndex] = matrix[i - 1, colIndex]; 
            }
            matrix[0, colIndex] = last;
        }
        
        for (int i = 0 ; i < row ; i++) {
            ShiftRow(i);
        }
        for (int i = 0 ; i < col ; i++) {
            ShiftColumn(i);
        }
    }
    

    You don't actually need them to be inner methods. I just find this way to be more readable. Inline them if you like.