이 험난한 세상에서어어~

배열 돌리기 3 본문

algorithm/코딩 테스트

배열 돌리기 3

토끼띠NJW 2023. 6. 1. 11:46

문제 설명

https://www.acmicpc.net/problem/16935

 

16935번: 배열 돌리기 3

크기가 N×M인 배열이 있을 때, 배열에 연산을 R번 적용하려고 한다. 연산은 총 6가지가 있다. 1번 연산은 배열을 상하 반전시키는 연산이다. 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 →

www.acmicpc.net

그야 말로 배열을 돌리는 문제다. 배열을 돌리는 온갖 신박한 방법 6가지를 함수로 구현해주면 된다. 여기서 중요한 건 배열의 인덱스 오류를 조심해야 한다. 특히 입력받는 배열이 정방 행렬이 아니기 때문에 90도로 돌려주는 부분에서는 본래 배열의 열과 행을 바꿔서 결과를 저장해야 한다.

 

첫 번째 연산은 상하를 반전시키는 방법이다. 두 번째 연산은 좌우를 반전시키는 방법이고 세 번재 방법은 시계방향으로 90도, 네 번째 방법은 반시계 방향으로 90도 회전하는 방법이다. 다섯 번째 방법은 배열을 총 4등분 해서 1번 그룹을 2번으로 2번 그룹을 3번으로, 3번을 4번, 4번을 1번으로 바꾸는 것이다. 마지막 여섯 번째 방법은 배열을 다섯 번쨍 ㅘ 같이 4등분 한 후 1번을 4번, 4번으 3번, 3번을 2번, 2번을 1번으로 바꾼다.

 

위의 백준 사이트에 회전 방법은 자세히 나와 있으므로 문제를 보고 직접 참고하면 문제를 더 쉽게 이해할 수 있을 것이다.

 

문제 풀이

첫 번째 접근

구현 문제 답게 문제에 설명된 그대로 코드를 짜면 된다.

 

일단 첫 번째 연산의 경우 단순히 열을 바꾸는 문제이기 때문에 나는 본래의 배열의 맨 뒤의 열부터 새로운 배열에 차례대로 붙여줬다. 이때 reversed를 사용해서 배열을 맨 뒤부터 가지고 오도록 했다.

 

두 번째 연산은 좌우 반전이기에 열은 변하지 않고 행만 바뀌는 연산이다. 가장 왼쪽에 있는 숫자부터 가장 오른쪽으로 가야 하므로 새로운 배열의 행 값에 'm-1-j'를 넣어줬다. 

 

세 번째 연산은 시계방향 90도로 회전하는 연산이다. 여기서 정말 정말 정말 중요한 부분이 있는데, 바로 새롭게 만들 배열의 크기이다. 90도로 돌리면 행과 열의 길이가 뒤바뀌게 된다. 그러므로 새로운 배열의 크기는 본래 배열의 행과 열의 길이를 바꿔서 설정해야 한다.

만일 정방행렬이라면 신경쓰지 않아도 되지만, 이 문제에서는 n과 m이 다르니까.

시계 방향으로 90도 돌리는 경우 본래 있었던 행의 값이 열이 되고(n-1)에다가 본래 있었던 열의 값을 빼주면 새로운 배열의 행의 값이 된다.

a            t

(0,0) -> (0,3)

(0,1) -> (1,3)

(0,2) -> (2,3)

(0,3) -> (3,3)

이렇게.

위의 변화를 보면 t 배열의 행의 경우 3으로 고정되고 열만이 a의 행에 따라 바뀌는 것을 볼 수 있다. 또한 t 배열의 행은 a 배열의 열의 길이(t 배열의 행의 길이)에다가 1과 a의 열을 빼준 값이다.

그리고 위의 연산을 마쳤다면 꼭 n과 m을 바꿔서 배열의 크기가 달라졌음을 알려줘야 한다!

 

네 번째 연산은 시계 반대방향 90도 회전은 위의 시계 방향 90도 회전을 살짝만 변형하면 된다.

a           t

(0,0) -> (4,0)

(0,1) -> (3,0)

(0,2) -> (2,0)

(0,3) -> (1,0)

(0,4) -> (0,0)

a의 열을 t의 행으로 고정시키고 t의 열은 n-1-a의 행으로 넣어주면 된다.

여기서도 해당 연산을 마치면 꼭 n과 m을 바꿔서 배열의 크기가 달라졌음을 명시하도록 하자.

 

다섯 번째 연산은 배열을 총 4군데로 쪼개서 옮겨주는 방식이다. 처음에는 배열을 진짜로 쪼개야하나 생각했지만 총 4번의 1차원 반복문으로 배열을 바꿔줄 수 있다.

참고로 말하자면 배열은 열과 행이 모두 2의 배수이기 때문에 나누는 데에는 문제가 없다.

 

여섯 번째 연산은 다섯 번째 연산과 같이 배열을 4군데로 쪼갠 다음 연산을 해주는 방식이다. 이때도 문제를 보고 풀어주면 된다.

 

문제가 복잡해 보일지 몰라도 인덱스에 벗어나지 않게 신경만 써주면 그렇게 어렵지 않은 문제다. 꼭 직접 손으로 쓰면서 배열을 돌려보고 코드를 짜도록 하자! 그래야지 왜 아래의 연산을 통해서 배열을 바꿔주는지 이해가 된다.

 

코드

import sys
import copy

n, m, r = map(int, sys.stdin.readline().rstrip().split(" "))


def one(a):
    tmp = []

    for i in reversed(range(n)):
        tmp.append(a[i])

    return tmp

def two(a):
    tmp = [[0 for _ in range(m)] for _ in range(n)]

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

    return tmp

def three(a):
    tmp = [[0 for _ in range(n)] for _ in range(m)]

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

    return tmp

def four(a):
    tmp = [[0 for _ in range(n)] for _ in range(m)]

    for i in range(len(a)):
        for j in range(len(a[0])):
            tmp[len(a[0])-1-j][i] = a[i][j]

    return tmp

def five(a):

    tmp = [[0 for _ in range(m)] for _ in range(n)]


    for i in range(n//2):
        for j in range(m//2):
            tmp[i][j+m//2] = arr[i][j]

    for i in range(n//2):
        t = (i+n//2)
        for j in range(m//2, m):
            tmp[t][j] = a[i][j]

    for i in range(n//2, n):
        for j in range(m//2, m):
            tmp[i][j - m//2] = a[i][j]

    for i in range(n//2, n):
        for j in range(m//2):
            tmp[i-n//2][j] = a[i][j]

    return tmp

def six(a):
    tmp = [[0 for _ in range(m)] for _ in range(n)]

    for i in range(n//2):
        for j in range(m//2):
            tmp[i+n//2][j] = a[i][j]

    for i in range(n//2):
        for j in range(m//2, m):
            tmp[i][j-m//2] = a[i][j]

    for i in range(n//2, n):
        for j in range(m//2, m):
            tmp[i-n//2][j] = a[i][j]

    for i in range(n//2, n):
        for j in range(m//2):
            tmp[i][j+m//2] = a[i][j]

    return tmp


def move(arr):
    a = []

    for i in range(len(arr)):
        a.append(arr[i])

    return a

def show(a):
    n = len(a)
    m = len(a[0])

    for i in range(n):
        for j in range(m):
            print(a[n][m], end = ' ')
        print()


arr = []

for i in range(n):
    arr.append(list(map(int, sys.stdin.readline().rstrip().split(" "))))

orders = list(map(int, sys.stdin.readline().rstrip().split(" ")))

for order in orders:
    if order == 1:
        a = one(arr)
        arr = copy.deepcopy(a)
    elif order == 2:
        a = two(arr)
        arr = copy.deepcopy(a)
    elif order == 3:
        a = three(arr)
        arr = copy.deepcopy(a)
        n,m = m,n
    elif order == 4:
        a = four(arr)
        arr = copy.deepcopy(a)
        n,m = m,n
    elif order == 5:
        a = five(arr)
        arr = copy.deepcopy(a)
    elif order == 6:
        a = six(arr)
        arr = copy.deepcopy(a)


for i in range(len(arr)):
    for j in range(len(arr[0])):
        print(arr[i][j] , end = ' ')

    print()

 

'algorithm > 코딩 테스트' 카테고리의 다른 글

프로그래머스, 덧칠하기(python)  (0) 2023.06.02
추억 점수  (0) 2023.06.02
아기 상어(백준 16236, python)  (0) 2023.05.29
배열 돌리기  (0) 2023.05.28
백준(20291), 파일 정리 python  (0) 2023.05.22