꺼내먹는지식 준
SW Expert Academy 6109 문제 (행렬회전) 본문
SW Expert Academy 6109 문제. 추억의 2048게임
문제링크: https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWbrg9uabZsDFAWQ
문제
입력:
각 테스트 케이스의 첫 번째 줄에는 하나의 정수 N(1≤N≤20)과 하나의 문자열 S가 공백 하나로 구분되어 주어진다. S는 “left”, “right”, “up”, “down”의 넷 중 하나의 값이 주어지며, 각각 타일들을 왼쪽, 오른쪽, 위쪽, 아래쪽으로 이동시킨다는 뜻이다. 다음 N개의 줄의 i번째 줄에는 N개의 정수가 공백 하나로 구분되어 주어진다. 이 정수들은 0이거나 2이상 1024이하의 2의 제곱수들이다. i번째 줄의 j번째 정수는 격자의 위에서 i번째 줄의 왼쪽에서 j번째에 있는 칸에 있는 타일에 어떤 정수가 적혀 있는지 나타내며, 0이면 이 칸에 타일이 없음을 의미한다.
출력:
각 테스트 케이스마다 ‘#t’(t는 테스트케이스 번호를 의미하며 1부터 시작한다)를 출력하고 한 줄을 띄운 후, N줄에 걸쳐 격자의 어떤 위치에 어떤 숫자가 적힌 타일이 있는지 입력 형식과 같은 형식으로 출력한다.
예시
입력:
2
5 up
4 8 2 4 0
4 4 2 0 8
8 0 2 4 4
2 2 2 2 8
0 2 2 0 0
2 down
16 2
0 2
출력:
#1
8 8 4 8 8
8 4 4 2 4
2 4 2 0 8
0 0 0 0 0
0 0 0 0 0
#2
0 0
16 4
풀이
단순 구현 문제
다만, right, left, up, down 을 한번에 처리해주기 위해서 회전행렬 개념을 정리한다.
회전행렬이란, 아래 그림과 같이 말그대로 행렬을 회전시키는 것이다.
좌표값 위치 변화에 맞춰 값의 위치가 이동한다.
90도 회전
모든 문제가 그렇듯, 잘 살펴보면 규칙이 보인다.
\[ [y,x] \rightarrow [x, N-1-y] \]
[0,0] $\rightarrow$ [0,2]
[0,1] $\rightarrow$ [1,2]
[0,2] $\rightarrow$ [2,2]
0 $\rightarrow$ 2, 1 $\rightarrow$ 1 , 2 $\rightarrow$ 0 $: N -1 - y $
180도 회전
마찬가지로 규칙이 존재한다.
\[ [y,x] \rightarrow [N-1-y ,N-1-x] \]
[0,0] $\rightarrow$ [2,2]
[0,1] $\rightarrow$ [2,1]
[0,2] $\rightarrow$ [2,0]
해당 문제에서 요구하는 회전 행렬은 다음의 3경우이다.
1) left $\rightarrow$ right
\[ [y,x] \rightarrow [y ,N-1-x] \]
2) left $\rightarrow$ up
\[ [y,x] \rightarrow [x,y] \]
3)left $\rightarrow$ down
\[ [y,x] \rightarrow [N-1-x, y] \]
def game(value):
global line
global stack
if value != 0:
if len(stack) == 0:
stack.append(value)
else:
if stack[-1] == value:
stack[-1] += value
line += stack
stack = []
else:
stack.append(value)
T = int(input())
for test_case in range(1, T + 1):
n, direction = input().split()
n = int(n)
data = [None] * n
for i in range(n):
data[i] = list(map(int, input().split()))
f_data = [[0] * n for _ in range(n)]
if direction == "left":
for i in range(n):
stack = []
line = []
for j in range(n):
game(data[i][j])
line += stack
for k in range(len(line)):
f_data[i][k] = line[k]
elif direction == "right":
for i in range(n):
stack = []
line = []
for j in range(n):
game(data[i][n-1-j])
line += stack
for k in range(len(line)):
f_data[i][n-1-k] = line[k]
elif direction == "up":
for i in range(n):
stack = []
line = []
for j in range(n):
game(data[j][i])
line += stack
for k in range(len(line)):
f_data[k][i] = line[k]
elif direction == "down":
for i in range(n):
stack = []
line = []
for j in range(n):
game(data[n-1-j][i])
line += stack
for k in range(len(line)):
f_data[n-1-k][i] = line[k]
for i in range(n):
print(' '.join(map( str, f_data[i])))
하지만 파이썬의 특징을 이용해서 회전 행렬을 쉽게 구현할 수 있다.
lst = [[1,2,3],[4,5,6],[7,8,9]]
list(zip(*lst[::-1] ))
출력
[(7, 4, 1), (8, 5, 2), (9, 6, 3)]
살펴보자면 먼저 [::-1] 로 리스트 원소의 순서를 바꾼다.
[[7,8,9], [4,5,6], [1,2,3]]
그 후, * 로 unpacking 하고 zip 으로 묶어준다. 즉
zip([7,8,9], [4,5,6], [1,2,3]) 이 되고 list 를 취해준다.
결과적으로
[[7,4,1], [8,5,2], [9,6,3]]
으로 90도 회전된다. 필요한 각도에 따라 회전을 시켜주면 된다.
'코딩테스트총정리 > 구현' 카테고리의 다른 글
프로그래머스 조이스틱 그리디 (0) | 2022.05.12 |
---|---|
SW Expert 아카데미 4112. 이상한 피라미드 탐험 (0) | 2022.02.12 |
2018 KAKAO BLIND RECRUITMENT 2번 문제 (0) | 2022.02.12 |
2022 KAKAO BLIND RECRUITMENT 3번 문제 (0) | 2022.02.12 |
백준 11578 팀원 모집 (0) | 2022.02.12 |