본문 바로가기
CS/알고리즘 & 문제풀이

[Python] 백준 16926 / 16927 배열 돌리기 1, 2

by mintropy 2021. 10. 12.

문제 링크

배열 돌리기 1 : https://www.acmicpc.net/problem/16926

 

16926번: 배열 돌리기 1

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

배열 돌리기 2 : https://www.acmicpc.net/problem/16927

 

16927번: 배열 돌리기 2

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

1. 접근 방법

두 문제는 R 조건, 회전하는 횟수를 제외하고 모두 같은 조건이다. 그래서 배열 돌리기 1을 먼저 풀고 배열 돌리기 2를 확인했을 때, 완전히 같은 문제임을 알고 같은 코드로 제출했다. 사실 배열 돌리기 2를 확인하지 않고 작성한 코드를 작성하고 사용했다.

이러한 문제의 가장 중요한 부분은 반복을 줄일 수 있는가에 관한 부분이다. 그리고 이러한 이유 때문에 두 문제 모두 효율적으로 풀어냈다.

 

 

2. 해결 코드

🖥python 코드

import sys
input = sys.stdin.readline
MIIS = lambda: map(int, input().split())


def rotate(array, pos, r):
    tmp = []
    # 반시계 방향으로 저장
    for i in range(pos, n - pos):
        tmp.append(array[i][pos])
    for i in range(pos + 1, m - pos):
        tmp.append(array[n - 1 - pos][i])
    for i in range(n - 1 - pos - 1, pos - 1, -1):
        tmp.append(array[i][m - 1 - pos])
    for i in range(m - 1 - pos - 1, pos, -1):
        tmp.append(array[pos][i])
    # r개 후의 것을 뽑아서 다시 순회하며 입력
    idx = (0 - r) % len(tmp)
    for i in range(pos, n - pos):
        array[i][pos] = tmp[idx]
        idx = (idx + 1) % len(tmp)
    for i in range(pos + 1, m - pos):
        array[n - 1 - pos][i] = tmp[idx]
        idx = (idx + 1) % len(tmp)
    for i in range(n - 1 - pos - 1, pos - 1, -1):
        array[i][m - 1 - pos] = tmp[idx]
        idx = (idx + 1) % len(tmp)
    for i in range(m - 1 - pos - 1, pos, -1):
        array[pos][i] = tmp[idx]
        idx = (idx + 1) % len(tmp)    
    return array


n, m, r = MIIS()
array = [list(MIIS()) for _ in range(n)]

for i in range(min(n // 2, m // 2)):
    # 한 바퀴 기준 개수
    points = 0
    # 세로로 개수
    points += (n - i * 2) * 2
    # 가로로 개수
    points += (m - (i + 1) * 2) * 2
    # 여러번 회전하지 않도록 회수 계산
    points = r % points
    rotate(array, i, points)

for line in array:
    print(*line)

📕 풀이 방법

(0, 0)부터 (n // 2, m // 2) 위치까지 대각선으로 들어가며 확인하는 것으로 시작한다.

해당하는 점을 기준으로, 한 바퀴씩 확인하며 회전을 하는데, 한 바퀴의 길이를 기준으로 여러 번 회전하지 않도록 한다.

그 외의 회전 구현은 단순한 인덱스 구현이라, 어렵지 않게 해결할 수 있을 것 같다.

 

 

3. 생각 정리

배열 돌리기 1도 충분히 빠른 속도로 해결했지만, 배열 돌리기 2에서 그 효과가 확실하게 나타난 것 같다.

항상 빠른 코드, 짧은 코드가 좋다고 말할수는 없다. 이번 코드도 for문을 여러 번 반복하는 것을 더 압축하지 못한 것이 아쉽다는 생각도 든다. 하지만, 문제를 풀어가는 더 효율적인 알고리즘, 풀이 방법을 알아가는 과정은 즐겁다.

댓글