티스토리 뷰
https://www.acmicpc.net/problem/16935
1. 접근 방식
- 각 연산을 처리하는 함수를 구현하자.
각 함수는 인자로 기존 배열을 받고, 연산을 적용한 결과(배열)을 반환한다. 함수 내부에서 일어나는 일이 외부에 영향을 끼치고 싶지 않았기 때문에 이와 같이 배열을 인자로 받고, 새 배열을 반환하는 방식으로 구현하고자 한다.
- 인덱싱과 리스트 comprehension을 활용하자.
연산 1 ~ 4는 인덱싱과 리스트 comprehension으로 모두 간단하게 해결할 수 있다.
그 중 연산 3을 살펴보자.
위 그림에서 왼쪽은 입력 배열이고, 오른쪽은 연산3이 처리된 결과이다. 오른쪽 배열을 얻기 위한 과정은 크게 2가지로 나뉜다.
첫째, 기존 배열을 열을 기준으로 접근한다. 열별로 접근하는 코드는 아래와 같다.
[ [ ... ] for i in range(len(arr[0])) ] # [ ... ]은 과정 2 코드
둘째, 각 열에서 행은 거꾸로 접근한다. 즉, 0행부터가 아니라, 5행부터 접근하는 것이다. 따라서 위쪽처럼 1 7 1 7 9 4가 아니라, 아래쪽처럼 4 9 7 1 7 1의 결과가 나와야 옳다.
[row[i] for row in arr[::-1]] # [ ... ]에 해당하는 코드
최종적으로 연산 3의 최종 처리 코드는 다음과 같다.
[[row[i] for row in arr[::-1]] for i in range(len(arr[0]))]
- 연산 5, 6하기 전에, 먼저 하나의 배열을 그룹별로 4개로 쪼개자.
연산 5와 6에서 사용되므로, 따로 get_groups()라는 함수를 구현한다.
함수 내에서는 우선 4개의 배열을 구하기 위해 범위를 설정한다. 순서는 1번 그룹에서부터 4번 그룹순이며, 시작 위치(좌측 상단)와 끝 위치(우측 하단)의 위치를 담는다.
rc = [
[(0, 0), (n // 2, m // 2)], [(0, m // 2), (n // 2, m)],
[(n // 2, m // 2), (n, m)], [(n // 2, 0), (n, m // 2)]
]
위 범위 배열을 순회하면서 기존 배열에서 각 그룹별로 배열을 추출하여 결과 리스트에 담는다. 결과 리스트의 첫 번째 원소엔 1번 그룹 배열이, 두 번째 원소엔 2번 그룹 배열, 세 번째 원소엔 3번 그룹 배열, 네 번째 원소엔 4번 그룹 배열이 들어가며, 함수는 그 결과를 반환한다.
- 연산 5, 6에서는 zip 내장 함수를 활용하자.
연산 5을 예시로 살펴보자.
현재 그룹은 빨간색, 노란색, 파란색, 초록색 총 4개의 그룹으로 나뉘어져 있다. 새 배열에서는 0행에는 각 4번 그룹 배열의 0행과 1번 그룹 배열의 0행이 들어간다. 1행에는 4번 그룹 배열의 1행과 1번 그룹 배열의 1행이 들어가며, 2행 역시 마찬가지이다. 새 배열의 3행에는 이제 3번 그룹 배열의 0행과 2번 그룹 배열의 0행부터 쭉 들어간다.
result = []
for four, one in zip(groups[-1], groups[0]):
result.append(four + one)
for three, two in zip(groups[-2], groups[1]):
result.append(three + two)
따라서 위 코드처럼 4번 그룹 배열과 1번 그룹 배열을 zip으로 처리하고, 3번 그룹 배열과 2번 그룹 배열을 zip으로 처리하면 쉽게 최종 배열 result를 생성할 수 있다.
2. 정답 코드
import sys
input = sys.stdin.readline
def cmd1_upside_down(arr):
return arr[::-1]
def cmd2_switch_sides(arr):
return [row[::-1] for row in arr]
def cmd3_rotate_90_to_the_right(arr):
return [[row[i] for row in arr[::-1]] for i in range(len(arr[0]))]
def cmd4_rotate_90_to_the_left(arr):
return [[row[i] for row in arr] for i in range(len(arr[0]) - 1, -1, -1)]
def cmd5_rotate_group_clockwise(arr):
groups = get_groups(arr)
result = []
for four, one in zip(groups[-1], groups[0]):
result.append(four + one)
for three, two in zip(groups[-2], groups[1]):
result.append(three + two)
return result
def cmd6_rotate_group_counterclockwise(arr):
groups = get_groups(arr)
result = []
for two, three in zip(groups[1], groups[-2]):
result.append(two + three)
for one, four in zip(groups[0], groups[-1]):
result.append(one + four)
return result
def get_groups(arr):
n, m = len(arr), len(arr[0])
rc = [
[(0, 0), (n // 2, m // 2)], [(0, m // 2), (n // 2, m)],
[(n // 2, m // 2), (n, m)], [(n // 2, 0), (n, m // 2)]
]
groups = []
for start, end in rc:
groups.append(list(
[arr[i][j] for j in range(start[1], end[1])] for i in range(start[0], end[0])
))
return groups
# main
n, m, r = map(int, input().split())
array = [list(map(int, input().split())) for _ in range(n)]
command = list(map(int, input().split()))
for cmd in command:
if cmd == 1:
array = cmd1_upside_down(array)
elif cmd == 2:
array = cmd2_switch_sides(array)
elif cmd == 3:
array = cmd3_rotate_90_to_the_right(array)
elif cmd == 4:
array = cmd4_rotate_90_to_the_left(array)
elif cmd == 5:
array = cmd5_rotate_group_clockwise(array)
elif cmd == 6:
array = cmd6_rotate_group_counterclockwise(array)
for row in array:
print(" ".join(list(map(str, row))))
'코딩 테스트 > 백준' 카테고리의 다른 글
[백준] 1991번 트리 순회 파이썬 풀이 (0) | 2023.08.14 |
---|---|
[백준] 16925번 배열 돌리기 1 파이썬 풀이 (0) | 2023.08.14 |
[백준] 20056번 마법사 상어와 파이어볼 파이썬 풀이 (+ 새 정답 코드 추가) (0) | 2023.08.11 |
[백준] 2805번 나무 자르기 파이썬 풀이 (0) | 2023.08.09 |
[백준] 15903번 카드 합체 놀이 파이썬 풀이 (0) | 2023.08.08 |