본문 바로가기

python

[python] 시계방향 및 반시계방향 회전

 

오랜만에 제 글 봤는데 저도 이해 안되길래 수정했습니다 (24.08.28)

 

계기

  • 코딩 테스트 준비를 하다보면, 2차원 배열 전체 혹은 일부를 회전하는 문제가 등장함
  • 반시계 방향, 시계 방향을 즉석에서 구현하기 힘드니 암기를 해야 함
  • 때론 회전한 후의 좌표를 명확히 알아야 해서 다음 좌표가 어떻게 생겼는지 구할 줄 알아야 함
  • 시험장에서도 기억날 수 있는 방법이 필요해

 

암기하면 위험할 수도 있는 공식들

A = list(map(list, zip(*arr[::-1])))
  • 이렇게 한 줄로 된 공식은 암기하기 편하긴 함
  • 하지만 행렬 전체가 아니라 행렬 일부만 회전하는 문제들이 등장함
  • 응용할 줄 알겠다면 상관 없으나 나처럼 for 문으로 외우는 게 안전할 것 같으면 읽어보자

 

직관적으로 암기 말고 이해부터 하기

1. 시계 방향 90도 회전 = 대각선 대칭 이동 + 좌우 대칭 이동

시계 방향 90도 회전 = 대각선 대칭 이동 + 좌우 대칭 이동
  • 못 믿겠다고? 예시로 보자

 

[원본]
1 2 3
4 5 6

[대각선 대칭 이동]
1 4
2 5
3 6

[좌우 대칭 이동]
4 1
5 2
6 3

 

  • 결론적으로 시계 방향 90도 회전이 되었다.
  • 만약 좌우 대칭이 아니라 상하 대칭 이동하면 어떨까?

 

2. 반시계 방향 90도 회전 = 대각선 대칭 이동 + 상하 대칭 이동

[원본]
1 2 3
4 5 6

[대각선 대칭 이동]
1 4
2 5
3 6

[상하 대칭 이동]
3 6
2 5
1 4
  • 반시계 90도 회전이 되었다

 

코드로 구현해보기

# r = num_of_row, c = num_of_c

arr = [
[1, 2, 3],
[4, 5, 6]
]

r, c = len(arr), len(arr[0])
  • 우선 예제를 2 X 3 인 2차원 배열을 만들었다
  • 내 공식은 '가장 왼쪽이면서 가장 위쪽인 좌표'를 [0][0]으로 규정할 때 적용가능함
  • 참고로 arr[x][y] 로 값에 접근한다
  • 예컨대, arr[0][1] = 2, arr[1][2] = 6 이다
  • 즉, arr[x][y] 로 하기로 했으니 x가 세로를 담당하고 y 가 가로를 담당한다
  • r은 row, c는 column을 의미함

 

1. 대각선 대칭 이동

new_x = old_y
new_y = old_x
  • 일단 원본에서 대각선을 기준으로 뒤집어보자

 

for i in range(r):
	for j in range(c):
		new_arr[j][i] = old_arr[i][j]
  • for 문으로 구현하는 이렇게 된다. 어렵지 않다.

 

2. 좌우 대칭 이동

new_x = old_x
new_y = (r - 1) - old_y
  • y 가 가로라고 위에서 말했음. 그러므로 y값에 변화를 줘야 좌우대칭이 됨.
  • r: 행렬의 가로 길이 (일단 행렬 전체를 회전한다고 가정)

 

for i in range(r):
	for j in range(c):
		new_arr[i][(r - 1) - j] = old_arr[i][j]
  • for문은 이렇게 생겼을 듯

 

3. 시계 방향 90도 회전 = 대각선 대칭 이동 + 좌우 대칭 이동

# 시계방향 90도 회전
new_x = old_y
new_y = (r - 1) - old_x

 

  • 대각선 대칭 이동 후에 좌우 대칭 공식 합하면 이렇게 됨

 

for i in range(r):
	for j in range(i + 1, c):
		new_arr[j][(r - 1) - i] = old_arr[i][j]

 

 

 

시험장에서 어떻게 해야 하나

  1. 기억 안 나면, '대각선 대칭 이동' + '머시기 이동'만 기억한다
  2. '머시기 이동'이 좌우가 시계인지, 반시계인지 헷갈리면 위처럼 작은 행렬 그려서 확인해본다

 

더 잘 하고 싶다면

  • 어려운 문제는 전체 배열이 아닌 일부만 잘라서 이동시키기 때문에 주의해야 한다
  • 특히 위 공식은 (0,0)이 좌측 상단 꼭짓점일 때 가능하므로, 아닌 경우엔 대칭 이동시켜야 한다

 

(0, 0)이 아닌 경우: 대칭 이동 예제

# sx, sy: 회전해야 할 영역의 좌측 상단 꼭짓점

for i in range(sx, sx + r):
	for j in  range(sy, sy + c):
    	ox, oy = i - sx, j - sy # (0, 0) 으로 이동
        nx, ny = oy, (r - 1) - ox # 시계 방향 90도 이동
        new_arr[nx + sx][ny + sy] = old_arr[i][j]