Language/Python

[Python] 2차원 배열 회전 : zip( ), 인덱스를 고려한 회전

위시리 2024. 10. 10. 14:46

1. zip( ) 활용

정사각형, 직사각형 모두 적용 가능하다.

  • 시계 방향 90 ( = 반시계방향 270 )
arr = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

arr90 = list(map(list, zip(*arr[::-1])))
print(arr90)

# [[9, 5, 1], [10, 6, 2], [11, 7, 3], [12, 8, 4]]
  • 시계 방향 180  ( = 반시계 방향 180 )
arr = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

arr180 = [a[::-1] for a in arr[::-1]]
print(arr180)

# [[12, 11, 10, 9], [8, 7, 6, 5], [4, 3, 2, 1]]
  • 시계 방향 270 ( = 반시계 방향 90 )
arr = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

arr270 = [x[::-1] for x in list(map(list, zip(*arr[::-1])))[::-1]]
print(arr270)

# [[4, 8, 12], [3, 7, 11], [2, 6, 10], [1, 5, 9]]
  • 외우고 있다면 빠르게 구현 가능
  • 장점 : 정사각형, 직사각형 둘 다 적용 가능하고, 배열의 인덱스 고민없이 빠르게 처리할 수 있다.
  • 단점 : 메모리나 시간 복잡도 면에서는 인덱스 규칙을 찾아서 회전하는 것보다 좋지 않다.

 

2. 인덱스 규칙 찾아서 회전

정사각형

  • 시계 방향 90 ( = 반시계 방향 270 )
arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
n = 3

new90 = [[0] * n for _ in range(n)]
for i in range(n) :
    for j in range(n) :
        new90[j][n-i-1] = arr[i][j]

print(new90)

# [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
  • 시계 방향 180 ( = 반시계 방향 180 )
arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
n = 3

new180 = [[0] * n for _ in range(n)]
for i in range(n) :
    for j in range(n) :
        new180[n-j-1][n-i-1] = arr[i][j]

print(new180)

# [[9, 6, 3], [8, 5, 2], [7, 4, 1]]
  • 시계 방향 270 ( = 반시계 방향 90 )
arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
n = 3

new270 = [[0] * n for _ in range(n)]
for i in range(n) :
    for j in range(n) :
        new270[n-j-1][i] = arr[i][j]

print(new270)

# [[3, 6, 9], [2, 5, 8], [1, 4, 7]]

 

직사각형

  • 시계 방향 90 ( = 반시계 방향 270 )
def rotated_90(a) :
    w = len(a) # 세로 길이 -> 가로
    h = len(a[0]) # 가로 길이 -> 세로
    result = [[0] * w for _ in range(h)]

    for i in range(w) : # 원래 배열 a는 w가 세로였기 때문에 w를 먼저 돌아야 한다.
        for j in range(h) :
            result[j][w-i-1] = a[i][j]

    return result

a = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
print(rotated_90(a))

# [[9, 5, 1], [10, 6, 2], [11, 7, 3], [12, 8, 4]]
N Before After
1 (0, 0) (0,2)
2 (0, 1) (1,2)
3 (0, 2) (2,2)
4 (0, 3) (3,2)

 

    기존의 i 행은 [ h - 1 + i ] 열로 이동
    기존의 j 열은 로 이동 새로운 행 j 로 이동
  • 시계 방향 180 ( = 반시계 방향 180 )
def rotated_180(a) :
    m = len(a) # 세로 길이 -> 가로
    n = len(a[0]) # 가로 길이 -> 세로
    result = [[0] * m for _ in range(n)]

    for i in range(m) :
        for j in range (n) :
            result[n-j-1][m-i-1] = a[i][j]

    return result

a = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
print(rotated_180(a))

# [[12, 8, 4], [11, 7, 3], [10, 6, 2], [9, 5, 1]]
  • 시계 방향 270 ( = 반시계 방향 90 )
def rotated_270(a) :
    m = len(a) # 세로 길이 -> 가로
    n = len(a[0]) # 가로 길이 -> 세로
    result = [[0] * m for _ in range(n)]

    for i in range(m) :
        for j in range (n) :
            result[n-j-1][i] = a[i][j]

    return result

a = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
print(rotated_270(a))

# [[4, 8, 12], [3, 7, 11], [2, 6, 10], [1, 5, 9]]

 

3. 부분 회전

2차원 배열의 특정 부분만 회전시키는 것

7x7 배열 arr의 일부 영역을 시계방향으로 90도 회전

arr = [[7 * j + i for i in range(1,8)] for j in range(7)]
new_arr = [[0] * 7 for _ in range(7)]

print('원본 : ')
for i in range(len(arr)) :
    print(arr[i])

sh, sw = 2,2 # 시작점 인덱스
length = 3 # 회전시킬 정사각형의 한 변의 길이

# 배열의 특정 부분 회전
def ro90(sh, sw, length) :
    global arr, new_arr

    # 정사각형 90도 회전
    for h in range(sh, sh + length) :
        for w in range(sw, sw + length) :
            # 1. (2,2) 지점에서 각 좌표를 (0,0) 기준으로 변환
            # 정사각형의 영역의 원점에서 얼마나 떨어져 있는지 계산
            oh, ow = h - sh, w - sw
            # 2. 90도 회전한 좌표 계산
            rh, rw = ow, length - oh - 1
            # 3. 회전 좌표에 맞게 new_arr에 값 복사 : 다시 (sh,sw)를 더해줌
            new_arr[sh + rh][sw + rw] = arr[h][w]

    # new_arr 의 값을 원본 배열 arr에 반영
    for h in range(sh, sh + length) :
        for w in range(sw, sw + length) :
            arr[h][w] = new_arr[h][w]
            # print(arr[h][w])

ro90(sh, sw, length)

print('시계 방향 90 회전 : ')
for i in range(len(arr)) :
    print(arr[i])

결과

 

REFERENCE

https://velog.io/@rhdmstj17/%EC%82%BC%EC%84%B1-%EC%9D%B8%EC%9E%AC%EC%9B%90-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84-%EC%88%99%EC%A7%80%ED%95%98%EA%B3%A0-%EB%93%A4%EC%96%B4%EA%B0%80%EB%A9%B4-%EC%A2%8B%EC%9D%80-%EB%B9%88%EC%B6%9C-%EC%BD%94%EB%93%9C-%EC%9C%A0%ED%98%95-6%EA%B0%80%EC%A7%80

 

SW 역량 테스트 치르기 전 숙지하면 좋을 삼성 빈출 코드 유형 정리 🕵🏼‍♀️🌀🦈

삼성 기출에서 자주 나오는 코드 유형들을 추려봤습니다 혹시 자주 나오는 또다른 유형이 있다면 댓글로 알려주시면 감사하겠습니다 🙇🏻‍♀️

velog.io

https://velog.io/@mjieun/Python-2%EC%B0%A8%EC%9B%90-%EB%B0%B0%EC%97%B4-%ED%9A%8C%EC%A0%84-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9E%90%EB%AC%BC%EC%87%A0%EC%99%80-%EC%97%B4%EC%87%A0-1wtw2wp8

 

[Python] 2차원 배열 회전 알고리즘 ( 프로그래머스 : 자물쇠와 열쇠 )

행과 열의 수가 같은 정방형 배열(square array 또는 square matrix) 에서 2차원 배열을 오른쪽으로 90도 회전 시키는 방법에 대해 알아보자.

velog.io