[백준] 16935 (배열 돌리기 3)
#PS#BOJ#tier:g5#implementation

[백준] 16935 (배열 돌리기 3)

문제 요약

N×MN\times M 크기의 2차원 배열에 6가지 연산을 총 RR번 적용해야 합니다. 연산은 상하/좌우 반전, 90도 회전, 그리고 4개의 부분 배열(사분면) 단위 이동으로 구성되어 있습니다.

이전에 두 정삼각형 문제 풀이에서 2차원 배열의 회전과 대칭을 '좌표 변환'의 관점에서 깊이 다룬 적이 있습니다. 이번에는 Python의 기능인 슬라이싱과 zip을 이용해 인덱스 계산을 하지 않고 직관적으로 해결하는 방법을 설명해 보겠습니다.

해설

일반적인 프로그래밍 언어에서는 반복문으로 B[new_r][new_c] = A[r][c]와 같은 방식으로 배열 좌표를 하나씩 옮깁니다. 하지만 Python에서는 배열 전체를 하나의 '모양'으로 다루는 것이 훨씬 효율적이고 구현 실수도 적습니다.

  1. 배열의 대칭 (1, 2번 연산)

상하 반전은 행의 순서를 뒤집는 것과 같으므로, 전체 리스트를 역순으로 하는 스트라이딩을 활용해 A[::-1]와 같이 구현할 수 있습니다.

좌우 반전은 각 행 내부의 원소 순서를 뒤집는 것과 같으므로, 스트라이딩과 리스트 컴프리헨션을 활용해 [row[::-1] for row in A]와 같이 구현할 수 있습니다.

  1. 배열의 회전 (3, 4번 연산)

'두 정삼각형' 풀이에서 90도 회전을 "대각선 대칭(Transpose)과 수직선 대칭의 합성"으로 설명했던 것을 기억하시나요? Python의 zip을 이용하면 이를 한 줄로 처리할 수 있습니다.

오른쪽 90도 회전은 zip(*A[::-1])와 같이 구현할 수 있습니다. 위아래 대칭 뒤 transpose한 것과 같기 때문입니다.

반시계 90도 회전은 zip(*A)[::-1]와 같이 구현할 수 있습니다. Transpose한 뒤 위아래 대칭한 것과 같기 때문입니다.

  1. 배열의 사분면 이동 (5, 6번 연산)

배열을 4등분하는 것은 슬라이싱으로 처리할 수 있습니다.

저는 A1(좌상), A2(우상), A3(좌하), A4(우하)로 정의한 뒤, 문제에서 요구하는 순서대로 이어 붙일 때 + 연산자를 사용했습니다.

배울 점

이 문제와 비슷한 류의 문제들로 연습하면, Python의 기능을 활용해 인덱스 계산을 하지 않고 직관적으로 해결하는 방법을 익힐 수 있습니다. 구현 복잡도가 훨씬 낮기 때문에 컴퓨터의 시간과 메모리는 더 쓰겠지만 '맞았습니다'를 더 빨리 받을 수 있습니다.