StepUp
StepUp

Reputation: 38209

Change elements in an array

I've puzzled over this not usual task for a days to figure out an appropriate algorithm. Let's say I have 2D array:

int[][] jagged = new int[4][];
jagged[0] = new int[4] { 1, 2, 3, 4 };
jagged[1] = new int[4] { 5, 6, 7, 8 };
jagged[2] = new int[4] { 9, 10, 11, 12 };
jagged[3] = new int[4] { 13, 14, 15, 16 };

How can I rotate this matrix in counter-clockwise direction to be like the following?

1  2  3  4             2 3 4 8           3 4 8 12
5  6  7  8    -->      1 7 11 12   -->   2 11 10 16 
9  10 11 12            5 6 10 16         1 7  6  15 
13 14 15 16            9 13 14 15        5 9  13 14

2D array can have various dimensions. I mean 2x3, or 3x4.

I've tried to use the following algorithm, but it rotates just to 90 degrees:

int [,] newArray = new int[4,4];

for (int i=3;i>=0;--i)
{
    for (int j=0;j<4;++j)
    {
         newArray[j,3-i] = array[i,j];
    }
}

If I change increments, then it does give me nothing. Maybe is there another solution?

Upvotes: 1

Views: 259

Answers (2)

dcg
dcg

Reputation: 4219

I know this question is answered but I wanted to do it for a general matrix of nxm. It takes into account the corner cases where the matrix has only one column or row.

public static void Rotate(int[,] matrix)
{
    // Specific cases when matrix has one only row or column
    if (matrix.GetLength(0) == 1 || matrix.GetLength(1) == 1)
        RotateOneRowOrColumn(matrix);
    else
    {
        int min = Math.Min(matrix.GetLength(0), matrix.GetLength(1)),
        b = min / 2, r = min % 2;

        for (int d = 0; d < b + r; d++)
        {
            int bkp = matrix[d, d];
            ShiftRow(matrix, d, d, matrix.GetLength(1) - d - 1, true);
            ShiftColumn(matrix, matrix.GetLength(1) - d - 1, d, matrix.GetLength(0) - d - 1, false);
            ShiftRow(matrix, matrix.GetLength(0) - d - 1, d, matrix.GetLength(1) - d - 1, false);
            ShiftColumn(matrix, d, d + 1, matrix.GetLength(0) - d - 1, true);
            if (matrix.GetLength(0) - 2 * d - 1 >= 1)
                matrix[d + 1, d] = bkp;
       }
    }
}

private static void RotateOneRowOrColumn(int[,] matrix)
{
    bool isRow = matrix.GetLength(0) == 1;
    int s = 0, e = (isRow ? matrix.GetLength(1) : matrix.GetLength(0)) - 1;

    while (s < e)
    {
        if (isRow)
            Swap(matrix, 0, s, 0, e);
        else
            Swap(matrix, s, 0, e, 0);
        s++; e--;
    }
}

public static void Swap(int[,] matrix, int from_x, int from_y, int to_x, int to_y)
{
    //It doesn't verifies whether the indices are correct or not
    int bkp = matrix[to_x, to_y];
    matrix[to_x, to_y] = matrix[from_x, from_y];
    matrix[from_x, from_y] = bkp;
}

public static void ShiftColumn(int[,] matrix, int col, int start, int end,  bool down)
{
    for (int i = down ? end - 1 : start + 1; (down && i >= start) || (!down && i <= end); i += down ? -1 : 1)
    { matrix[i + (down ? 1 : -1), col] = matrix[i, col]; }
}

 public static void ShiftRow(int[,] matrix, int row, int start, int end, bool left)
{
    for (int j = left ? start + 1 : end - 1; (left && j <= end) || (!left && j >= start); j += (left ? 1 : -1))
    { matrix[row, j + (left ? -1 : 1)] = matrix[row, j]; }
}

Upvotes: 1

Dmitry
Dmitry

Reputation: 14059

Assuming each "square" of an array rotates independently.
You could use the following code snippet:

const int ArraySize = 4;
int[,] array = 
                {
                    { 2, 3, 4, 8 },
                    { 1, 7, 11, 12 },
                    { 5, 6, 10, 16 },
                    { 9, 13, 14, 15 }
                };

for (int r = (ArraySize - 1) / 2; r >= 0; r--)
{
    int start = r;
    int end = ArraySize - r - 1;
    int saveTopLeft = array[start, start];

    // Top
    for (int i = start; i <= end - 1; i++)
        array[start, i] = array[start, i + 1];

    // Right
    for (int i = start; i <= end - 1; i++)
        array[i, end] = array[i + 1, end];

    // Bottom
    for (int i = end; i >= start + 1; i--)
        array[end, i] = array[end, i - 1];

    // Left
    for (int i = end; i >= start + 2; i--)
        array[i, start] = array[i - 1, start];

    // Saved element
    array[start + 1, start] = saveTopLeft;
}

Upvotes: 2

Related Questions