1

Say I have multidimensional array like this:

int arr[3][3] = {{1, 2, 3},
                 {4, 5, 6},
                 {7, 8, 9}};

I'd like to rotate the array clockwise so it looks like this:

{{7, 4, 1},
 {8, 5, 2},
 {9, 6, 3}};

I tried swapping each of the values in turn with their previous value:

    swap(&arr[0][0],&arr[0][1]);
    swap(&arr[0][1],&arr[0][2]);
    swap(&arr[0][2],&arr[1][2]);
    swap(&arr[1][2],&arr[2][2]);
    swap(&arr[2][2],&arr[2][1]);
    swap(&arr[2][1],&arr[2][0]);
    swap(&arr[2][0],&arr[1][0]);
    swap(&arr[1][0],&arr[0][0]);

This didn't rotate correctly. It left a few values where they were and put the others in the wrong places.

What am I doing wrong, and how can I achieve this?

DEADBEEF
  • 525
  • 1
  • 5
  • 19
  • 1
    @DavidBowling Fixed. – DEADBEEF Jun 13 '17 at 00:01
  • Similar [question](https://stackoverflow.com/questions/40832947/array-rotation-in-c/) – BLUEPIXY Jun 13 '17 at 00:02
  • what is `swap`? You should show your code, and preferably post a [MCVE](http://stackoverflow.com/help/mcve) – M.M Jun 13 '17 at 00:02
  • @M.M `swap` is just a typical integer-swapping algorithm. I know it works, I tested it with other code. I don't want to include *everything* in the question because then it won't be Minimal. – DEADBEEF Jun 13 '17 at 00:03
  • @BLUEPIXY The answer to that is *terrible*. – DEADBEEF Jun 13 '17 at 00:04
  • 1
    @dasblinkenlight Fixed. – DEADBEEF Jun 13 '17 at 00:05
  • 1
    at the moment it's not Complete. Minimal means "minimal , whilst still being complete". – M.M Jun 13 '17 at 00:07
  • 2
    Anyway, your algorithm doesn't actually do a rotation, if you do it with pen and paper even you will see that you don't get the right result (and it should become apparent what you are doing wrong) – M.M Jun 13 '17 at 00:08
  • There are a lot of methods to choose from here: [How do you rotate a two dimensional array?](https://stackoverflow.com/q/42519/445976) – Blastfurnace Jun 13 '17 at 00:11

2 Answers2

4

You might note that after rotation, the elements of the first row of the rotated array come from the first column of the original array, in reverse order with respect to the indices. Similarly, the second row of the rotated array comes from the second column of the original array, and so on. With this in mind, you can write a function that fills a new array with appropriate values from the original array, before copying the new values into the original array.

The function rotate_array() iterates over the array rotated. The elements of the ith row of rotated come from the ith column of the input array a. The jth element of ith row of rotated is the n-j-1th element of the ith column of a. The memcpy() function is then used to copy the contents of the rotated array into the original array.

#include <stdio.h>
#include <string.h>

void print_array(size_t n, int a[n][n]);
void rotate_array(size_t n, int a[n][n]);

int main(void)
{
    size_t arr_sz = 5;
    int arr[arr_sz][arr_sz];

    for (size_t i = 0; i < arr_sz; i++) {
        for (size_t j = 0; j < arr_sz; j++) {
            arr[i][j] = i * arr_sz + j + 1;
        }
    }

    puts("Before rotation:");
    print_array(arr_sz, arr);
    putchar('\n');

    rotate_array(arr_sz, arr);
    puts("After rotation:");
    print_array(arr_sz, arr);
    putchar('\n');

    return 0;
}

void print_array(size_t n, int a[n][n])
{
    for (size_t i = 0; i < n; i++) {
        for (size_t j = 0; j < n; j++) {
            printf("%5d", a[i][j]);
        }
        putchar('\n');
    }
}

void rotate_array(size_t n, int a[n][n])
{
    int rotated[n][n];
    for (size_t i = 0; i < n; i++) {
        for (size_t j = 0; j < n; j++) {
            rotated[i][j] = a[n - j - 1][i];
        }
    }
    memcpy(a, rotated, sizeof a[0][0] * n * n);
}
Before rotation:
    1    2    3    4    5
    6    7    8    9   10
   11   12   13   14   15
   16   17   18   19   20
   21   22   23   24   25

After rotation:
   21   16   11    6    1
   22   17   12    7    2
   23   18   13    8    3
   24   19   14    9    4
   25   20   15   10    5
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • `rotated[i][j] = a[n - j - 1][i];` for rotating array in clockwise. `rotated[rows - j - 1][i] = arr[i][j];` for rotating array in anti-clockwise. `rotated[j][i] = a[n - j - 1][i];` for rotating array in flip vertical. – Johnny Aug 06 '20 at 05:59
2

You do not need eight swaps to rotate the matrix, because the last two swaps put two items in their places. The additional swaps put their operands into wrong spots again.

The center item is left in its place. First four swaps place four items in their new spots; the last two pairs are taking each others' new spots, so only two swaps are sufficient to complete the rotation.

swap(&arr[0][0], &arr[2][0]);
swap(&arr[0][1], &arr[1][0]);
swap(&arr[0][2], &arr[2][0]);
swap(&arr[1][0], &arr[2][1]);
swap(&arr[1][2], &arr[2][1]);
swap(&arr[2][2], &arr[2][0]);

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks! Out of curiosity, how would I rotate it counter-clockwise, just reverse the code? – DEADBEEF Jun 13 '17 at 00:33
  • You can interchange the array indices on each line of code; for example, [2][0] would become [0][2]. [Try it online!](https://tio.run/##hVHbToQwFHymXzFiNMB2DRSvwfVHkAcou0oil3RZfSB8O56WSzZkoydNOu3MmTkFuf2Qchiui0p@nfI9Xo9tXtR3n28M7Lsuchx/0sYpqtZDykE7vMxFxywN27LBDl4aMctLNco0yggRE7F@9mgUqbUJyjhMaBmHQ61gLhU1@Ihov9oh1GCzMQpQLSo5qeSskqQaNbpMxsGxb3LYnHJUEsvEjUbBTL5Xtr7qzWhmnrSoHD3j8qZpQgrruoALHvYc3T3HA8ejhk8czxwvfR@xxdkp3bMT5WynGvNgOPMhb8vYT2hxjEgkU@fMBudssGbFn72mw7DBBVb8x4qV8@p9ltq3J1XBpx87DL8 "C (gcc) – Try It Online") – musicman523 Jun 13 '17 at 01:06
  • @heythere Curiously, the last two lines are the same. The first four do change to pick items from opposite sides. Here is a [modified demo](http://ideone.com/uQLKpu). – Sergey Kalinichenko Jun 13 '17 at 01:12