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.
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.