Featured image of post 16935번 : 배열 돌리기 3 (Python)

16935번 : 배열 돌리기 3 (Python)

BOJ 16935번 배열 돌리기 3 Python 풀이

문제 링크 : https://www.acmicpc.net/problem/16935

문제

크기가 N×M인 배열이 있을 때, 배열에 연산을 R번 적용하려고 한다. 연산은 총 6가지가 있다.

1번 연산은 배열을 상하 반전시키는 연산이다.

1
2
3
4
5
6
7
1 6 2 9 8 4 → 4 2 9 3 1 8
7 2 6 9 8 2 → 9 2 3 6 1 5
1 8 3 4 2 9 → 7 4 6 2 3 1
7 4 6 2 3 1 → 1 8 3 4 2 9
9 2 3 6 1 5 → 7 2 6 9 8 2
4 2 9 3 1 8 → 1 6 2 9 8 4
   <배열>        <연산 결과>

2번 연산은 배열을 좌우 반전시키는 연산이다.

1
2
3
4
5
6
7
1 6 2 9 8 4 → 4 8 9 2 6 1
7 2 6 9 8 2 → 2 8 9 6 2 7
1 8 3 4 2 9 → 9 2 4 3 8 1
7 4 6 2 3 1 → 1 3 2 6 4 7
9 2 3 6 1 5 → 5 1 6 3 2 9
4 2 9 3 1 8 → 8 1 3 9 2 4
   <배열>        <연산 결과>

3번 연산은 오른쪽으로 90도 회전시키는 연산이다.

1
2
3
4
5
6
7
1 6 2 9 8 4 → 4 9 7 1 7 1
7 2 6 9 8 2 → 2 2 4 8 2 6
1 8 3 4 2 9 → 9 3 6 3 6 2
7 4 6 2 3 1 → 3 6 2 4 9 9
9 2 3 6 1 5 → 1 1 3 2 8 8
4 2 9 3 1 8 → 8 5 1 9 2 4
   <배열>        <연산 결과>

4번 연산은 왼쪽으로 90도 회전시키는 연산이다.

1
2
3
4
5
6
7
1 6 2 9 8 4 → 4 2 9 1 5 8
7 2 6 9 8 2 → 8 8 2 3 1 1
1 8 3 4 2 9 → 9 9 4 2 6 3
7 4 6 2 3 1 → 2 6 3 6 3 9
9 2 3 6 1 5 → 6 2 8 4 2 2
4 2 9 3 1 8 → 1 7 1 7 9 4
   <배열>        <연산 결과>

5, 6번 연산을 수행하려면 배열을 크기가 N/2×M/2인 4개의 부분 배열로 나눠야 한다. 아래 그림은 크기가 6×8인 배열을 4개의 그룹으로 나눈 것이고, 1부터 4까지의 수로 나타냈다.

1
2
3
4
5
6
1 1 1 1 2 2 2 2
1 1 1 1 2 2 2 2
1 1 1 1 2 2 2 2
4 4 4 4 3 3 3 3
4 4 4 4 3 3 3 3
4 4 4 4 3 3 3 3

5번 연산은 1번 그룹의 부분 배열을 2번 그룹 위치로, 2번을 3번으로, 3번을 4번으로, 4번을 1번으로 이동시키는 연산이다.

1
2
3
4
5
6
7
3 2 6 3 1 2 9 7 → 2 1 3 8 3 2 6 3
9 7 8 2 1 4 5 3 → 1 3 2 8 9 7 8 2
5 9 2 1 9 6 1 8 → 4 5 1 9 5 9 2 1
2 1 3 8 6 3 9 2 → 6 3 9 2 1 2 9 7
1 3 2 8 7 9 2 1 → 7 9 2 1 1 4 5 3
4 5 1 9 8 2 1 3 → 8 2 1 3 9 6 1 8
     <배열>             <연산 결과>

6번 연산은 1번 그룹의 부분 배열을 4번 그룹 위치로, 4번을 3번으로, 3번을 2번으로, 2번을 1번으로 이동시키는 연산이다.

1
2
3
4
5
6
7
3 2 6 3 1 2 9 7 → 1 2 9 7 6 3 9 2
9 7 8 2 1 4 5 3 → 1 4 5 3 7 9 2 1
5 9 2 1 9 6 1 8 → 9 6 1 8 8 2 1 3
2 1 3 8 6 3 9 2 → 3 2 6 3 2 1 3 8
1 3 2 8 7 9 2 1 → 9 7 8 2 1 3 2 8
4 5 1 9 8 2 1 3 → 5 9 2 1 4 5 1 9
     <배열>             <연산 결과>

입력

첫째 줄에 배열의 크기 $N$, $M$과 수행해야 하는 연산의 수 R이 주어진다.

둘째 줄부터 $N$개의 줄에 배열 $A$의 원소 $A_{ij}$가 주어진다.

마지막 줄에는 수행해야 하는 연산이 주어진다. 연산은 공백으로 구분되어져 있고, 문제에서 설명한 연산 번호이며, 순서대로 적용시켜야 한다.

출력

입력으로 주어진 배열에 $R$개의 연산을 순서대로 수행한 결과를 출력한다.

제한

  • $2 \leq N, M \leq 100$
  • $1 \leq R \leq 1,000$
  • $N$, $M$은 짝수
  • $1 \leq A_{ij} \leq 10^8$

소스 코드

 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
26
27
28
29
30
31
import sys

input = sys.stdin.readline
n, m, r = map(int, input().split())
arr = [[int(x) for x in input().split()] for _ in range(n)]
options = [int(x) for x in input().split()]

for option in options:
    if option == 1:
        arr = arr[::-1]  # 상하 반전
    elif option == 2:
        arr = list(map(lambda x: x[::-1], arr))  # 좌우 반전
    elif option == 3:
        arr = list(zip(*arr[::-1]))  # 오른쪽으로 90도 회전
        n, m = m, n  # 행, 열 사이즈 스왑
    elif option == 4:
        arr = list(map(list, zip(*arr)))[::-1]  # 왼쪽으로 90도 회전
        n, m = m, n
    else:
        arr1 = map(lambda x: x[:m//2], arr[:n//2])  # 1사분면
        arr2 = map(lambda x: x[m//2:], arr[:n//2])  # 2사분면
        arr3 = map(lambda x: x[:m//2], arr[n//2:])  # 3사분면
        arr4 = map(lambda x: x[m//2:], arr[n//2:])  # 4사분면
        if option == 5:  # 시계 방향 사분면 회전
            arr = list(zip(arr3, arr1)) + list(zip(arr4, arr2))
        elif option == 6:  # 반시계 방향 사분면 회전
            arr = list(zip(arr2, arr4)) + list(zip(arr1, arr3))
        arr = list(map(lambda x: x[0]+x[1], arr))

for row in arr:
    print(*row)

풀이

풀이는 소스코드를 참고해 주세요

후기

좀 귀찮은 문제였는데, 깔끔하게 구현해 보려고 노력했다. 파이썬 리스트컴프리헨션을 연습하기 좋은 문제였다.