2차원 배열 시계 방향 90도 회전
문제
배열을 입력받아 시계 방향으로 90도 회전된 결과를 만드는 함수를 작성하시오.
1 * 3
input:
[
[ 1, 2, 3 ]
]
output:
[
[ 1 ],
[ 2 ],
[ 3 ]
]
3 * 1
input:
[
[ 1 ],
[ 11 ],
[ 21 ]
]
output:
[
[ 21, 11, 1 ]
]
3 * 3
input:
[
[ 1, 2, 3 ],
[ 11, 12, 13 ],
[ 21, 22, 23 ]
]
output:
[
[ 21, 11, 1 ],
[ 22, 12, 2 ],
[ 23, 13, 3 ]
]
5 * 6
input:
[
[ 1, 2, 3, 4, 5, 6 ],
[ 11, 12, 13, 14, 15, 16 ],
[ 21, 22, 23, 24, 25, 26 ],
[ 31, 32, 33, 34, 35, 36 ],
[ 41, 42, 43, 44, 45, 46 ]
]
output:
[
[ 41, 31, 21, 11, 1 ],
[ 42, 32, 22, 12, 2 ],
[ 43, 33, 23, 13, 3 ],
[ 44, 34, 24, 14, 4 ],
[ 45, 35, 25, 15, 5 ],
[ 46, 36, 26, 16, 6 ]
]
풀이
#include <stdio.h>
#include <stdlib.h>
void RotateClockwise90Degrees(int row_count, int col_count, const int input[row_count][col_count], int output[col_count][row_count])
{
for (int row = 0; row < row_count; row++)
{
for (int col = 0; col < col_count; col++)
{
output[col][row_count - 1 - row] = input[row][col];
}
}
}
void PrintMatrix(int row_count, int col_count, const int* matrix)
{
for (int row = 0; row < row_count; row++)
{
for (int col = 0; col < col_count; col++)
{
printf("%3d", matrix[row * col_count + col]);
}
printf("\n");
}
}
void RunExample(const char* title, int row_count, int col_count, const int input[row_count][col_count])
{
int (*output)[row_count];
output = (int (*)[row_count])malloc(sizeof(int) * row_count * col_count);
if (output == NULL)
return;
printf("----- %s -----\n", title);
printf("input:\n");
PrintMatrix(row_count, col_count, input[0]);
RotateClockwise90Degrees(row_count, col_count, input, output);
printf("\noutput:\n");
PrintMatrix(col_count, row_count, output[0]);
printf("--------------------\n\n");
free(output);
}
int main(void)
{
const int input1[1][3] = {
{ 1, 2, 3 }
};
const int input2[3][1] = {
{ 1 },
{ 11 },
{ 21 }
};
const int input3[3][3] = {
{ 1, 2, 3 },
{ 11, 12, 13 },
{ 21, 22, 23 }
};
const int input4[5][6] = {
{ 1, 2, 3, 4, 5, 6 },
{ 11, 12, 13, 14, 15, 16 },
{ 21, 22, 23, 24, 25, 26 },
{ 31, 32, 33, 34, 35, 36 },
{ 41, 42, 43, 44, 45, 46 }
};
RunExample("1 * 3", 1, 3, input1);
RunExample("3 * 1", 3, 1, input2);
RunExample("3 * 3", 3, 3, input3);
RunExample("5 * 6", 5, 6, input4);
return 0;
}
원본 배열의 요소에 숫자 순서대로 접근하면, 현재 접근 중인 원소는 input[row][col]로 표현할 수 있다.
원본 배열에서는 열 인덱스인 col이 증가할수록 왼쪽에서 오른쪽으로 이동하지만, 결과 배열에서는 같은 값들이 행 인덱스가 증가하는 방향으로 놓인다.
따라서 결과 배열에서는 원본 배열의 열 인덱스인 col이 행 인덱스가 되므로 output[col][?] = input[row][col]; 형태가 된다.
이제 ?에 들어갈 결과 배열의 열 인덱스를 생각해보자.
5x6 배열을 기준으로 보면 원본 배열의 0번 행은 결과 배열의 마지막 열인 4번 열에 놓이고, 원본 배열의 1번 행은 3번 열에 놓인다.
원본 배열에서는 행 인덱스가 고정된 상태로 열 인덱스가 증가하지만, 결과 배열에서는 열 인덱스가 고정된 상태로 행 인덱스가 증가한다.
결과 배열의 마지막 열 인덱스는 row_count - 1이고, 원본 배열의 행 인덱스인 row가 증가할 때마다 결과 배열의 열 인덱스는 하나씩 줄어들어야 한다.
그래서 결과 배열의 열 인덱스는 row_count - 1 - row가 된다.
따라서 최종 식은 다음과 같다.
output[col][row_count - 1 - row] = input[row][col];
VLA를 지원하지 않는 환경에서는 다음처럼 포인터를 사용해 작성할 수도 있다.
void RotateClockwise90Degrees(int row_count, int col_count, const int* input, int* output)
{
for (int row = 0; row < row_count; row++)
{
for (int col = 0; col < col_count; col++)
{
output[col * row_count + (row_count - 1 - row)] = input[row * col_count + col];
}
}
}