성장기록지
클린 구현 프로젝트 2) 백준 16926 배열 돌리기 본문
문제
https://www.acmicpc.net/problem/16926
문제 해결
배열을 조건에 맞게 한칸씩 반시계 방향으로 돌리는 문제이다.
가로와 세로의 길이 중 작은값은 항상 짝수라는 조건이 있어서
가로 세로가 둘다 홀수일때의 예외처리를 해주지 않아도 되어서 좋았다.
만약 둘 다 홀수인 아래의 그림(N=5,M=7) 보면, 17~19까지 반시계로 회전을 할 수 없게 된다.
구조 설계
많은 변수와 함수가 필요하다고 생각되어 하나씩 설계해 나갔다.
초기의 배열을 의미하는 nums ,
회전 후 정답 배열을 의미하는 ans 를 구성하였고,
가로와 세로의 길이가 각자 다를 수 있으므로,
x와 y가 배열을 순회할때 가능한 시작점과 끝점을 의미하는
x_min, x_max 와 y_min, y_max 변수를 만들었다.
그 후 위의 그림처럼 빨간색 영역을 extract_edges 함수를 통해 deque에 저장하고,
덱의 rotation 기능을 통해 반시계방향으로 회전하도록 한 후,
fill_edges 함수를 통하여 정답 리스트에 값을 넣도록 하였다.
그 후 x,y의 min과 max를 1씩 늘리고 줄여 다음 영역(파란색)에서 동일한 동작을 하도록 하였다.
전체적인 코드는 다음과 같다.
from collections import deque
import sys
input = sys.stdin.readline
#입력받기
def read_input():
N, M, R = map(int, input().split())
nums = [list(map(int, input().split())) for _ in range(N)]
return N, M, R, nums
#배열을 추출
def extract_edges(nums, x_min, x_max, y_min, y_max):
temp = deque()
count = 0
# 위 배열
for i in range(y_min, y_max + 1):
temp.append(nums[x_min][i])
count += 1
# 오른쪽 배열
for j in range(x_min + 1, x_max):
temp.append(nums[j][y_max])
count += 1
# 아래 배열
for k in range(y_max, y_min - 1, -1):
temp.append(nums[x_max][k])
count += 1
# 왼쪽 배열
for l in range(x_max - 1, x_min, -1):
temp.append(nums[l][y_min])
count += 1
return temp, count
#회전한 값대로 배열 채우기
def fill_edges(ans, temp, x_min, x_max, y_min, y_max):
# 위 배열
for i in range(y_min, y_max + 1):
ans[x_min][i] = temp.popleft()
# 오른쪽 배열
for j in range(x_min + 1, x_max):
ans[j][y_max] = temp.popleft()
# 아래 배열
for k in range(y_max, y_min - 1, -1):
ans[x_max][k] = temp.popleft()
# 왼쪽 배열
for l in range(x_max - 1, x_min, -1):
ans[l][y_min] = temp.popleft()
def rotate_matrix(N, M, R, nums):
ans = [[-1 for _ in range(M)] for _ in range(N)]
x_min, y_min = 0, 0
x_max, y_max = N - 1, M - 1
while x_max > x_min and y_max > y_min:
temp, count = extract_edges(nums, x_min, x_max, y_min, y_max)
this_R = R % count
temp.rotate(-this_R)
#회전한 배열을 다시 채워넣는다.
fill_edges(ans, temp, x_min, x_max, y_min, y_max)
x_min += 1
y_min += 1
x_max -= 1
y_max -= 1
return ans
N, M, R, nums = read_input()
ans = rotate_matrix(N, M, R, nums)
for row in ans:
print(*row)
설계상의 디테일
deque의 rotate
리스트의 크기만큼 rotate를 하면 원점으로 돌아오므로 시간낭비라고 생각하여
this_R = R% count로 횟수를 줄였다.
기능별 함수 분리
기능들을 각각 함수로 분리하여
최대한 읽기 쉬운 코드를 구현하려고 노력하였다.
추가로 생각해볼 점
위 배열, 오른쪽 배열, 아래 배열, 왼쪽배열을
순회하는 코드도 함수로 만들어야 할까
파라미터가 너무 많이필요할거같아 오히려 가독성이 안좋을 수 있을거같아서
따로 함수로 구분하진 않았다.
조금 더 고민해보고 더 깔끔한 코드로 구현해야겠다.
'알고리즘 > 구현' 카테고리의 다른 글
백준) 2636 치즈 문제풀이 및 set() 활용 (0) | 2024.06.03 |
---|---|
깔끔하게 구현하기 프로젝트) 백준 17413 단어 뒤집기 2 (0) | 2024.05.13 |