[Python/프로그래머스/배열회전] 행렬 테두리 회전하기

문제

rows x columns 크기인 행렬이 있습니다. 행렬에는 1부터 rows x columns까지의 숫자가 한 줄씩 순서대로 적혀있습니다. 이 행렬에서 직사각형 모양의 범위를 여러 번 선택해, 테두리 부분에 있는 숫자들을 시계방향으로 회전시키려 합니다. 각 회전은 (x1, y1, x2, y2)인 정수 4개로 표현하며, 그 의미는 다음과 같습니다.

  • x1 행 y1 열부터 x2 행 y2 열까지의 영역에 해당하는 직사각형에서 테두리에 있는 숫자들을 한 칸씩 시계방향으로 회전합니다.

다음은 6 x 6 크기 행렬의 예시입니다.

이 행렬에 (2, 2, 5, 4) 회전을 적용하면, 아래 그림과 같이 2행 2열부터 5행 4열까지 영역의 테두리가 시계방향으로 회전합니다. 이때, 중앙의 15와 21이 있는 영역은 회전하지 않는 것을 주의하세요.

행렬의 세로 길이(행 개수) rows, 가로 길이(열 개수) columns, 그리고 회전들의 목록 queries가 주어질 때, 각 회전들을 배열에 적용한 뒤, 그 회전에 의해 위치가 바뀐 숫자들 중 가장 작은 숫자들을 순서대로 배열에 담아 return 하도록 solution 함수를 완성해주세요.

제한사항

  • rows는 2 이상 100 이하인 자연수입니다.
  • columns는 2 이상 100 이하인 자연수입니다.
  • 처음에 행렬에는 가로 방향으로 숫자가 1부터 하나씩 증가하면서 적혀있습니다.
    • 즉, 아무 회전도 하지 않았을 때, i 행 j 열에 있는 숫자는 ((i-1) x columns + j)입니다.
  • queries의 행의 개수(회전의 개수)는 1 이상 10,000 이하입니다.
  • queries의 각 행은 4개의 정수 [x1, y1, x2, y2]입니다.
    • x1 행 y1 열부터 x2 행 y2 열까지 영역의 테두리를 시계방향으로 회전한다는 뜻입니다.
    • 1 ≤ x1 < x2 ≤ rows, 1 ≤ y1 < y2 ≤ columns입니다.
    • 모든 회전은 순서대로 이루어집니다.
    • 예를 들어, 두 번째 회전에 대한 답은 첫 번째 회전을 실행한 다음, 그 상태에서 두 번째 회전을 실행했을 때 이동한 숫자 중 최솟값을 구하면 됩니다.

 

입출력 예시

row columns queries result
6 6 [[2,2,5,4],[3,3,6,6],[5,1,6,3]] [8, 10, 25]
3 3 [[1,1,2,2],[1,2,2,3],[2,1,3,2],[2,2,3,3]] [1, 1, 5, 3]
100 97 [[1,1,100,97]] [1]

 

나의 풀이

    answer = []
    array = [[0 for col in range(columns)] for row in range(rows)]
    t = 1
    for row in range(rows):
        for col in range(columns):
            array[row][col] = t
            t += 1

 

  먼저 행렬을 만들어줘야한다. 처음에는 값이 0으로 초기화된 rows*columns 크기의 배열을 만들어준다. 그 후, 가로방향으로 숫자가 1씩 증가하면서 적혀있는 형태이기 때문에 행과 열을 이동하면서 값을 할당해준다.

 

    for x1,y1,x2,y2 in queries:
        tmp = array[x1-1][y1-1]
        mini = tmp

        for k in range(x1-1,x2-1): #왼쪽 세로
            test = array[k+1][y1-1]
            array[k][y1-1] = test
            mini = min(mini, test)

  이제 주어진 queries를 보며 for문을 진행한다. quereis의 각 행은 4개의 정수 [x1, y1, x2, y2]로 이뤄져 있기 때문에 값의 이름을 문제와 똑같이 정해주었다. 먼저 왼쪽 세로부터 시작을 해준다. 하나의 값을 다른 하나의 값으로 옮기는 과정을 반복해야한다.

그림으로 확인을 해보면 이 부분의 이동이 이뤄지는 것이다. y 값은 y1-1 로 고정을 시켜주고 x값을 하나씩 증가시켜주며 진행한다. 이때 이동한 숫자 중 최솟값을 저장해야하기 때문에 min() 함수를 이용해 더 작은 값을 저장해둔다. 여기서 tmp를 왜 array[x1-1][y1-1]로 잡았는가는 array[x1-1][y1-1]값은 array[x-1][y1]로 이동을 해줘야 하는 값인데 이 for문에서는 왼쪽 세로 부분이기 때문에 상단 가로 for문이 돌아갈 때 옮겨질 예정인 값이다. 하지만 현재 값을 옮기면서 array[x-1][y-1]값이 다른 값으로 대체되기 때문에 그 값을 저장해서 마지막에 넣어주기 위해 가지고 있는 것이다. 이렇게 왼쪽 세로의 회전이 완성되었다. 

 

        for k in range(y1-1,y2-1): # 하단 가로
            test = array[x2-1][k+1]
            array[x2-1][k] = test
            mini = min(mini, test)

        for k in range(x2-1,x1-1,-1): # 왼쪽 세로
            test = array[k-1][y2-1]
            array[k][y2-1] = test
            mini = min(mini, test)

        for k in range(y2-1,y1-1,-1): # 상단 가로
            test = array[x1-1][k-1]
            array[x1-1][k] = test
            mini = min(mini, test)

  이어서 왼쪽 세로 -> 하단 가로 -> 오른쪽 세로 -> 상단 가로 순으로 회전을 진행해준다. 이렇게 모든 회전이 완료된다면 이 상태가 될 것이다.

 두 번째 코드 블록에서 설명했던 것처럼 array[x1-1][y1-1]값에는 값이 바뀌기 전의 array[x-1][y1]의 값이 입력이 돼야 하는데, 이 값이 초반에 다른 값으로 대체가 되었기 때문에 바뀐 이후의 값이 들어가게 된다. 

 

        array[x1-1][y1] = tmp
        answer.append(mini)

  그렇기 때문에 처음에 tmp에 저장한 값을 다시 array[x1-1][y1-1] 에 넣어주는 과정이 마지막에 들어가야 한다. 그 이후 회전한 값 중 제일 최솟값을 정답 배열에 추가해주면 한 회전이 끝난다!

 

전체 코드

def solution(rows, columns, queries):

    answer = []
    array = [[0 for col in range(columns)] for row in range(rows)]
    t = 1
    for row in range(rows):
        for col in range(columns):
            array[row][col] = t
            t += 1

    for x1,y1,x2,y2 in queries:
        tmp = array[x1-1][y1-1]
        mini = tmp

        for k in range(x1-1,x2-1):
            test = array[k+1][y1-1]
            array[k][y1-1] = test
            mini = min(mini, test)

        for k in range(y1-1,y2-1):
            test = array[x2-1][k+1]
            array[x2-1][k] = test
            mini = min(mini, test)

        for k in range(x2-1,x1-1,-1):
            test = array[k-1][y2-1]
            array[k][y2-1] = test
            mini = min(mini, test)

        for k in range(y2-1,y1-1,-1):
            test = array[x1-1][k-1]
            array[x1-1][k] = test
            mini = min(mini, test)

        array[x1-1][y1] = tmp
        answer.append(mini)

    return answer
 

코딩테스트 연습 - 행렬 테두리 회전하기

6 6 [[2,2,5,4],[3,3,6,6],[5,1,6,3]] [8, 10, 25] 3 3 [[1,1,2,2],[1,2,2,3],[2,1,3,2],[2,2,3,3]] [1, 1, 5, 3]

programmers.co.kr