2022. 1. 2. 00:14ㆍ알고리즘/구현
문제
루빅스 큐브는 삼차원 퍼즐이다. 보통 루빅스 큐브는 3×3×3개의 작은 정육면체로 이루어져 있다. 퍼즐을 풀려면 각 면에 있는 아홉 개의 작은 정육면체의 색이 동일해야 한다.
큐브는 각 면을 양방향으로 90도 만큼 돌릴 수 있도록 만들어져 있다. 회전이 마친 이후에는, 다른 면을 돌릴 수 있다. 이렇게 큐브의 서로 다른 면을 돌리다 보면, 색을 섞을 수 있다.
이 문제에서는 루빅스 큐브가 모두 풀린 상태에서 시작한다. 윗 면은 흰색, 아랫 면은 노란색, 앞 면은 빨간색, 뒷 면은 오렌지색, 왼쪽 면은 초록색, 오른쪽 면은 파란색이다.
루빅스 큐브를 돌린 방법이 순서대로 주어진다. 이때, 모두 돌린 다음에 가장 윗 면의 색상을 구하는 프로그램을 작성하시오.
위의 그림은 루빅스 큐브를 푼 그림이다. 왼쪽 면은 시계방향으로 조금 돌려져 있는 상태이다.
입력
첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스는 최대 100개이다. 각 테스트 케이스는 다음과 같이 구성되어져 있다.
- 첫째 줄에 큐브를 돌린 횟수 n이 주어진다. (1 ≤ n ≤ 1000)
- 둘째 줄에는 큐브를 돌린 방법이 주어진다. 각 방법은 공백으로 구분되어져 있으며, 첫 번째 문자는 돌린 면이다. U: 윗 면, D: 아랫 면, F: 앞 면, B: 뒷 면, L: 왼쪽 면, R: 오른쪽 면이다. 두 번째 문자는 돌린 방향이다. +인 경우에는 시계 방향 (그 면을 바라봤을 때가 기준), -인 경우에는 반시계 방향이다.
출력
각 테스트 케이스에 대해서 큐브를 모두 돌린 후의 윗 면의 색상을 출력한다. 첫 번째 줄에는 뒷 면과 접하는 칸의 색을 출력하고, 두 번째, 세 번째 줄은 순서대로 출력하면 된다. 흰색은 w, 노란색은 y, 빨간색은 r, 오렌지색은 o, 초록색은 g, 파란색은 b.
예제 입력 1
4 1 L- 2 F+ B+ 4 U- D- L+ R+ 10 L- U- L+ U- L- U- U- L+ U+ U+
예제 출력 1
rww rww rww bbb www ggg gwg owr bwb gwo www rww
접근 방법
- 어떤 면이 돌아갔을 때, 다른 면들이 어떻게 변하는 지를 파악한 뒤, 이를 반영하여 코드를 짠다.
- 1. 왼쪽 면이 돌아갔을 때
- - 시계방향인 경우: 윗면의 왼쪽 열 -> 앞면의 왼쪽 열 -> 아랫면의 왼쪽 열 -> 뒷면의 왼쪽 열 -> 윗면의 왼쪽 열 순으로 바뀐다.
- - 반시계방향인 경우: 윗면의 왼쪽 열 -> 뒷면의 왼쪽 열 -> 아랫면의 왼쪽 열 -> 앞면의 왼쪽 열 -> 윗면의 왼쪽 열 순으로 바뀐다.
- 2. 앞 면이 돌아갔을 때
- - 시계방향인 경우: 윗면의 아래 행 -> 오른쪽면의 왼쪽 열 -> 아랫면의 윗 행 -> 왼쪽면의 오른쪽 열 -> 윗면의 아래 행 순으로 바뀐다.
- - 반시계방향인 경우: 윗면의 아래 향 -> 왼쪽의 오른쪽 열 -> 아랫면의 윗 향 -> 오른쪽면의 왼쪽 열 -> 윗면의 아래 행 순으로 바뀐다.
- 3. 오른쪽 면이 돌아갔을 때
- - 시계방향인 경우: 윗면의 오른쪽 열 -> 뒷면의 오른쪽 열 -> 아랫면의 오른쪽 열 -> 앞면의 오른쪽 열 -> 윗면의 오른쪽 열 순으로 바뀐다.
- - 반시계방향인 경우: 윗면의 오른쪽 열 -> 앞면의 오른쪽 열 -> 아랫면의 오른쪽 열 -> 뒷면의 오른쪽 열 -> 윗면의 오른쪽 열 순으로 바뀐다.
- 4. 윗면이 돌아갔을 때
- - 시계방향인 경우: 왼쪽면의 윗 행 -> 뒷면의 아래행 -> 오른쪽면의 윗 행 -> 앞면의 윗행 순으로 바뀐다.
- - 반시계방향인 경우: 왼쪽면의 윗 행 -> 앞면의 윗 행 -> 오른쪽면의 윗행 -> 뒷면의 아래행 순으로 바뀐다.
- 5. 아래 면이 돌아갔을 때
- - 시계방향인 경우: 앞면의 아래 행 -> 오른쪽의 아래 행 -> 뒷면의 윗 행 -> 왼쪽면의 아래 행 -> 앞면의 아래 행
- - 반시계방향인 경우: 앞면의 아래 행 -> 왼쪽면의 아래행 -> 뒷면의 윗 행 -> 오른쪽면의 아래 행 -> 앞면의 아래 행
- 6. 뒷면이 돌아갔을 떄
- - 시계방향인 경우: 아래면의 아래 행 -> 오른쪽면의 오른쪽 행 -> 윗면의 윗 행 -> 왼쪽면의 왼쪽 행 -> 아래면의 아래 행
- - 반시계방향인 경우: 아래면의 아래 행 -> 왼쪽면의 왼쪽 행 -> 윗면의 윗 행 -> 오른쪽면의 오른쪽 행 -> 아래면의 아래 행
코드
# https://www.acmicpc.net/problem/5373
# 접근 방법
# 어떤 면이 돌아갔을 때, 다른 면들이 어떻게 변하는 지를 파악한 뒤, 이를 반영하여 코드를 짠다.
# 1. 왼쪽 면이 돌아갔을 때
# - 시계방향인 경우: 윗면의 왼쪽 열 -> 앞면의 왼쪽 열 -> 아랫면의 왼쪽 열 -> 뒷면의 왼쪽 열 -> 윗면의 왼쪽 열 순으로 바뀐다.
# - 반시계방향인 경우: 윗면의 왼쪽 열 -> 뒷면의 왼쪽 열 -> 아랫면의 왼쪽 열 -> 앞면의 왼쪽 열 -> 윗면의 왼쪽 열 순으로 바뀐다.
# 2. 앞 면이 돌아갔을 때
# - 시계방향인 경우: 윗면의 아래 행 -> 오른쪽면의 왼쪽 열 -> 아랫면의 윗 행 -> 왼쪽면의 오른쪽 열 -> 윗면의 아래 행 순으로 바뀐다.
# - 반시계방향인 경우: 윗면의 아래 향 -> 왼쪽의 오른쪽 열 -> 아랫면의 윗 향 -> 오른쪽면의 왼쪽 열 -> 윗면의 아래 행 순으로 바뀐다.
# 3. 오른쪽 면이 돌아갔을 때
# - 시계방향인 경우: 윗면의 오른쪽 열 -> 뒷면의 오른쪽 열 -> 아랫면의 오른쪽 열 -> 앞면의 오른쪽 열 -> 윗면의 오른쪽 열 순으로 바뀐다.
# - 반시계방향인 경우: 윗면의 오른쪽 열 -> 앞면의 오른쪽 열 -> 아랫면의 오른쪽 열 -> 뒷면의 오른쪽 열 -> 윗면의 오른쪽 열 순으로 바뀐다.
# 4. 윗면이 돌아갔을 때
# - 시계방향인 경우: 왼쪽면의 윗 행 -> 뒷면의 아래행 -> 오른쪽면의 윗 행 -> 앞면의 윗행 순으로 바뀐다.
# - 반시계방향인 경우: 왼쪽면의 윗 행 -> 앞면의 윗 행 -> 오른쪽면의 윗행 -> 뒷면의 아래행 순으로 바뀐다.
# 5. 아래 면이 돌아갔을 때
# - 시계방향인 경우: 앞면의 아래 행 -> 오른쪽의 아래 행 -> 뒷면의 윗 행 -> 왼쪽면의 아래 행 -> 앞면의 아래 행
# - 반시계방향인 경우: 앞면의 아래 행 -> 왼쪽면의 아래행 -> 뒷면의 윗 행 -> 오른쪽면의 아래 행 -> 앞면의 아래 행
# 6. 뒷면이 돌아갔을 떄
# - 시계방향인 경우: 아래면의 아래 행 -> 오른쪽면의 오른쪽 행 -> 윗면의 윗 행 -> 왼쪽면의 왼쪽 행 -> 아래면의 아래 행
# - 반시계방향인 경우: 아래면의 아래 행 -> 왼쪽면의 왼쪽 행 -> 윗면의 윗 행 -> 오른쪽면의 오른쪽 행 -> 아래면의 아래 행
import sys
def cubing(order, direction):
# 1. 왼쪽 면이 돌아갔을 때
# - 시계방향인 경우: 윗면의 왼쪽 열 -> 앞면의 왼쪽 열 -> 아랫면의 왼쪽 열 -> 뒷면의 왼쪽 열 -> 윗면의 왼쪽 열(역) 순으로 바뀐다.
# - 반시계방향인 경우: 윗면의 왼쪽 열 -> 뒷면의 왼쪽 열(역) -> 아랫면의 왼쪽 열 -> 앞면의 왼쪽 열 -> 윗면의 왼쪽 열 순으로 바뀐다.
if order == 'L':
front_, bottom_, back_, top_ = [[0, 0, 0] for _ in range(4)]
left_ = [[0, 0, 0] for _ in range(3)]
if direction == '+':
for i in range(3):
front_[i], bottom_[i], back_[i], top_[i] = top[i][0], front[i][0], bottom[i][0], back[i][0]
for j in range(3):
left_[j][2-i] = left[i][j]
else:
for i in range(3):
back_[i], bottom_[i], front_[i], top_[i] = top[i][0], back[i][0], bottom[i][0], front[i][0]
for j in range(3):
left_[2-j][i] = left[i][j]
for i in range(3):
front[i][0], bottom[i][0], back[i][0], top[i][0] = front_[i], bottom_[i], back_[i], top_[i]
for j in range(3):
left[i][j] = left_[i][j]
# 2. 앞 면이 돌아갔을 때
# - 시계방향인 경우: 윗면의 아래 행 -> 오른쪽면의 왼쪽 열 -> 아랫면의 윗 행(역) -> 왼쪽면의 오른쪽 열 -> 윗면의 아래 행(역) 순으로 바뀐다.
# - 반시계방향인 경우: 윗면의 아래 행 -> 왼쪽의 오른쪽 열(역) -> 아랫면의 윗 행 -> 오른쪽면의 왼쪽 열(역) -> 윗면의 아래 행 순으로 바뀐다.
if order == 'F':
right_, bottom_, left_, top_ = [[0, 0, 0] for _ in range(4)]
front_ = [[0, 0, 0] for _ in range(3)]
if direction == '+':
for i in range(3):
right_[i], bottom_[2-i], left_[i], top_[2-i] = top[2][i], right[i][0], bottom[0][i], left[i][2]
for j in range(3):
front_[j][2-i] = front[i][j]
else:
for i in range(3):
left_[2-i], bottom_[i], right_[2-i], top_[i] = top[2][i], left[i][2], bottom[0][i], right[i][0]
for j in range(3):
front_[2-j][i] = front[i][j]
for i in range(3):
top[2][i], right[i][0], bottom[0][i], left[i][2] = top_[i], right_[i], bottom_[i], left_[i]
for j in range(3):
front[i][j] = front_[i][j]
# 3. 오른쪽 면이 돌아갔을 때
# - 시계방향인 경우: 윗면의 오른쪽 열 -> 뒷면의 오른쪽 열(역) -> 아랫면의 오른쪽 열 -> 앞면의 오른쪽 열 -> 윗면의 오른쪽 열 순으로 바뀐다.
# - 반시계방향인 경우: 윗면의 오른쪽 열 -> 앞면의 오른쪽 열 -> 아랫면의 오른쪽 열 -> 뒷면의 오른쪽 열 -> 윗면의 오른쪽 열(역) 순으로 바뀐다.
if order == 'R':
front_, bottom_, back_, top_ = [[0, 0, 0] for _ in range(4)]
right_ = [[0, 0, 0] for _ in range(3)]
if direction == '+':
for i in range(3):
back_[i], bottom_[i], front_[i], top_[i] = top[i][2], back[i][2], bottom[i][2], front[i][2]
for j in range(3):
right_[j][2-i] = right[i][j]
else:
for i in range(3):
front_[i], bottom_[i], back_[i], top_[i] = top[i][2], front[i][2], bottom[i][2], back[i][2]
for j in range(3):
right_[2-j][i] = right[i][j]
for i in range(3):
front[i][2], bottom[i][2], back[i][2], top[i][2] = front_[i], bottom_[i], back_[i], top_[i]
for j in range(3):
right[i][j] = right_[i][j]
# 4. 윗면이 돌아갔을 때
# - 시계방향인 경우: 왼쪽면의 윗행 -> 뒷면의 아래행(역) -> 오른쪽면의 윗행 -> 앞면의 윗행 -> 왼쪽면의 윗행순으로 바뀐다.
# - 반시계방향인 경우: 왼쪽면의 윗행 -> 앞면의 윗행 -> 오른쪽면의 윗행 -> 뒷면의 아래행 -> 왼쪽면의 윗행(역)순으로 바뀐다.
if order == 'U':
back_, right_, front_, left_ = [[0, 0, 0] for _ in range(4)]
top_ = [[0,0,0] for _ in range(3)]
if direction == '+':
for i in range(3):
back_[2-i], right_[2-i], front_[i], left_[i] = left[0][i], back[2][i], right[0][i], front[0][i]
for j in range(3):
top_[j][2-i] = top[i][j]
else:
for i in range(3):
front_[i], right_[i], back_[2-i], left_[2-i] = left[0][i], front[0][i], right[0][i], back[2][i]
for j in range(3):
top_[2-j][i] = top[i][j]
for i in range(3):
left[0][i], back[2][i], right[0][i], front[0][i] = left_[i], back_[i], right_[i], front_[i]
for j in range(3):
top[i][j] = top_[i][j]
# 5. 아래 면이 돌아갔을 때
# - 시계방향인 경우: 앞면의 아래 행 -> 오른쪽의 아래 행 -> 뒷면의 윗 행(역) -> 왼쪽면의 아래 행 -> 앞면의 아래 행
# - 반시계방향인 경우: 앞면의 아래 행 -> 왼쪽면의 아래행 -> 뒷면의 윗 행 -> 오른쪽면의 아래 행(역) -> 앞면의 아래 행
if order == 'D':
back_, right_, front_, left_ = [[0, 0, 0] for _ in range(4)]
bottom_ = [[0,0,0] for _ in range(3)]
if direction == '+':
for i in range(3):
front_[i], right_[i], back_[2-i], left_[2-i] = left[2][i], front[2][i], right[2][i], back[0][i]
for j in range(3):
bottom_[j][2-i] = bottom[i][j]
else:
for i in range(3):
back_[2-i], right_[2-i], front_[i], left_[i] = left[2][i], back[0][i], right[2][i], front[2][i]
for j in range(3):
bottom_[2-j][i] = bottom[i][j]
for i in range(3):
left[2][i], back[0][i], right[2][i], front[2][i] = left_[i], back_[i], right_[i], front_[i]
for j in range(3):
bottom[i][j] = bottom_[i][j]
# 6. 뒷면이 돌아갔을 떄
# - 시계방향인 경우: 아래면의 아래 행 -> 오른쪽면의 오른쪽 행 -> 윗면의 윗 행(역) -> 왼쪽면의 왼쪽 행 -> 아래면의 아래 행(역)
# - 반시계방향인 경우: 아래면의 아래 행 -> 왼쪽면의 왼쪽 행(역) -> 윗면의 윗 행 -> 오른쪽면의 오른쪽 행(역) -> 아래면의 아래 행
if order == 'B':
bottom_, right_, top_, left_ = [[0, 0, 0] for _ in range(4)]
back_ = [[0,0,0] for _ in range(3)]
if direction == '+':
for i in range(3):
right_[2-i], top_[i], left_[2-i], bottom_[i] = bottom[2][i], right[i][2], top[0][i], left[i][0]
for j in range(3):
back_[j][2-i] = back[i][j]
else:
for i in range(3):
left_[i], top_[2-i], right_[i], bottom_[2-i] = bottom[2][i], left[i][0], top[0][i], right[i][2]
for j in range(3):
back_[2-j][i] = back[i][j]
for i in range(3):
bottom[2][i], right[i][2], top[0][i], left[i][0] = bottom_[i], right_[i], top_[i], left_[i]
for j in range(3):
back[i][j] = back_[i][j]
# print(order, direction)
# print('위:', top)
# print('왼:', left)
# print('앞:', front)
# print('오:', right)
# print('뒤:', back)
# print('바닥:', bottom)
# print()
for tc in range(int(sys.stdin.readline())):
n = int(sys.stdin.readline())
orders = list(sys.stdin.readline().split())
top = [['w' for _ in range(3)] for _ in range(3)]
bottom = [['y' for _ in range(3)] for _ in range(3)]
front = [['r' for _ in range(3)] for _ in range(3)]
back = [['o' for _ in range(3)] for _ in range(3)]
left = [['g' for _ in range(3)] for _ in range(3)]
right = [['b' for _ in range(3)] for _ in range(3)]
for i in range(n):
cubing(orders[i][0], orders[i][1])
for i in range(3):
print(top[i][0], top[i][1], top[i][2], sep='')
'알고리즘 > 구현' 카테고리의 다른 글
백준 온라인 저지, 구현 / 2441번: 별찍기3 (파이썬 / , 백준 브론즈문제) (0) | 2022.02.02 |
---|---|
백준 온라인 저지, 구현 / 2908번: 상수 (파이썬 / , 백준 브론즈문제) (0) | 2022.01.02 |
백준 온라인 저지, 구현 / 14499번: 주사위굴리기 (파이썬 / , 백준 골드문제, 삼성 SW 기출문제) (0) | 2021.12.20 |
백준 온라인 저지, 구현 / 14891번: 톱니바퀴 (파이썬 / , 백준 골드문제, 삼성 SW 기출문제) (0) | 2021.12.18 |
백준 온라인 저지, 구현 / 20055번: 컨베이어벨트위의로봇 (파이썬 / , 백준 실버문제, 삼성 SW 기출문제) (0) | 2021.12.16 |