2024년 새해를 맞아.. 새로운 문제집을 풀어보겠다.
좀 더 코테스러운 문제집을 골라왔다.
참고 여부 : X
소요 시간 : 1시간 30분
B자리에 R이 위치하게 될 때 B가 소실되는 문제점이 있었다. 이러한 TC를 찾느라 시간을 너무 많이 소비하였다.
다른 사람이 올려놓은 테케로 발견할 수 있었는데, 스스로 발견하지 못한 점이 아쉽다..
정답 코드
n, m = map(int, input().split())
origin_arr = []
R = [0, 0]
B = [0, 0]
hole = [0, 0]
for _ in range(n) :
tmp = input()
# origin_arr.append(list(input()))
index_r = tmp.find('R')
if (index_r != -1) :
R = [_, index_r]
index_b = tmp.find('B')
if (index_b != -1) :
B = [_, index_b]
index_hole = tmp.find('O')
if (index_hole != -1) :
hole = [_, index_hole]
origin_arr.append(list(tmp))
visited = set() # visited에 넣을땐 tuple로 넣기!
q = []
direction = [[-1, 0], [1, 0], [0, -1], [0, 1]] # 상하좌우
result = 9999999
current_r = R
current_b = B
q.append([R, B, 0])
visited.add(tuple([*R, *B]))
before_r = [0, 0]
before_b = [0, 0]
while (q) :
before_r = [current_r[0], current_r[1]]
before_b = [current_b[0], current_b[1]]
current_r, current_b, cnt = q.pop(0)
origin_arr[before_r[0]][before_r[1]] ='.'
origin_arr[current_r[0]][current_r[1]] = 'R'
if (origin_arr[before_b[0]][before_b[1]] != 'R') :
origin_arr[before_b[0]][before_b[1]] ='.'
origin_arr[current_b[0]][current_b[1]] = 'B'
cnt += 1
if (cnt > 10) :
continue
for dd in direction :
flag_r = False
flag_b = False
frontB = False
# 움직이고자 하는 방향에서 B가 먼저인지 파악
tmpy = current_r[0]
tmpx = current_r[1]
while (0 < tmpy + dd[0] < n - 1 and 0 < tmpx + dd[1] < m - 1) :
if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == '.') :
tmpy += dd[0]
tmpx += dd[1]
if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == 'B') :
frontB = True
break
if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == '#') :
break
if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == 'O') :
break
if not (frontB) :
yy, xx = current_r
while (0 < yy + dd[0] < n - 1 and 0 < xx + dd[1] < m - 1) :
if ((origin_arr[yy + dd[0]][xx + dd[1]] == '.') or (origin_arr[yy + dd[0]][xx + dd[1]] == 'O')) :
yy += dd[0]
xx += dd[1]
if (origin_arr[yy][xx] == 'O') :
flag_r = True
break
else :
break
origin_arr[current_r[0]][current_r[1]] = '.'
if not flag_r:
origin_arr[yy][xx] = 'R'
y, x = current_b
while ((0 < y + dd[0] < n - 1 and 0 < x + dd[1] < m - 1) and
(origin_arr[y + dd[0]][x + dd[1]] == '.' or origin_arr[y + dd[0]][x + dd[1]] == 'O')) :
y += dd[0]
x += dd[1]
if (origin_arr[y][x] == 'O') :
flag_b = True
break
origin_arr[current_b[0]][current_b[1]] = '.'
if not flag_b :
origin_arr[y][x] = 'B'
else :
y, x = current_b
while ((0 < y + dd[0] < n - 1 and 0 < x + dd[1] < m - 1) and
(origin_arr[y + dd[0]][x + dd[1]] == '.' or origin_arr[y + dd[0]][x + dd[1]] == 'O')) :
y += dd[0]
x += dd[1]
if (origin_arr[y][x] == 'O') :
flag_b = True
break
origin_arr[current_b[0]][current_b[1]] = '.'
if not flag_b :
origin_arr[y][x] = 'B'
yy, xx = current_r
while (0 < yy + dd[0] < n - 1 and 0 < xx + dd[1] < m - 1) :
if ((origin_arr[yy + dd[0]][xx + dd[1]] == '.') or (origin_arr[yy + dd[0]][xx + dd[1]] == 'O')) :
yy += dd[0]
xx += dd[1]
if (origin_arr[yy][xx] == 'O') :
flag_r = True
break
else :
break
origin_arr[current_r[0]][current_r[1]] = '.'
if not flag_r:
origin_arr[yy][xx] = 'R'
if (flag_r and not flag_b) :
result = min(result, cnt)
elif not (flag_b) :
if not tuple([yy, xx, y, x]) in visited :
visited.add(tuple([yy, xx, y, x]))
q.append([[yy, xx], [y, x], cnt])
if (origin_arr[yy][xx] == 'R') :
origin_arr[yy][xx] = '.'
origin_arr[current_r[0]][current_r[1]] = 'R'
elif (origin_arr[yy][xx] == 'O') :
origin_arr[current_r[0]][current_r[1]] = 'R'
if (origin_arr[y][x] == 'B') :
origin_arr[y][x] = '.'
origin_arr[current_b[0]][current_b[1]] = 'B'
elif (origin_arr[y][x] == 'R') :
origin_arr[current_b[0]][current_b[1]] = 'B'
elif (origin_arr[y][x] == 'O') :
origin_arr[current_b[0]][current_b[1]] = 'B'
if result == 9999999 :
print(-1)
else :
print(result)
참고 여부 : X
소요 시간 : 1시간 30분
up 방향의 함수를 하나 짜고 배열을 회전해서 인풋으로 넣어주려 하였다.
그런데 4개의 함수를 다 짜고 나서야 실수를 했다는 것을 깨달았다..
2 0 2
0 0 0
2 0 2
위의 배열에서 up 방향으로 움직이면
4 0 4
0 0 0
0 0 0
이러한 모양이 되어야하는데, 인접한 수만 고려하도록 짰다. 그래서 갈아엎었다.
이 문제에서 가장 헷갈리고 어려웠던건 배열을 원하는 방향으로 뒤집는 것이었다.
"zip(*arr)"을 통해서 transpose를 할 수 있다. Numpy를 쓰기엔 너무 낭비같다.
arr = list(map(list,zip(*arr)))
이렇게 하면 쉽게 전치 행렬을 얻을 수 있다.
참고 여부 : X
소요 시간 : 1시간 40분
뱀의 꼬리를 컨트롤하는게 생각보다 어려웠다..
5
2
2 5
2 4
6
4 D
5 D
6 D
7 D
8 D
9 D
해당 반례를 통해 내가 어디서 실수했는지 알 수 있었다.
뱀의 몸통을 1만으로 구성하고, 상하좌우를 탐색해 1이 있으면 그곳을 꼬리로 잡았는데
1 0
1 1
뱀이 이러한 꼴을 하고 있을 때 꼬리를 제대로 잡지 못하였다.
이를 보완하기 위해 뱀의 몸통을 current_time + 1로 하였다.
맨날 히든 테케에서 걸리는데.. 나 취업 가능?
# 사과 = -1
timer = 0
direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]
current_dir = 1
N = int(input())
arr = [[0] * N for _ in range(N)]
arr[0][0] = 1
k = int(input())
for _ in range(k) :
y, x = map(int, input().split())
arr[y - 1][x - 1] = -1
l = int(input())
change_time = []
for _ in range(l) :
x, c = input().split()
x = int(x)
change_time.append([x, c])
snake_head = [0, 0]
snake_tail = [0, 0]
current_time = -1
x, c = change_time.pop(0)
while (True) :
current_time += 1
# 시간 체크하면서 방향 바꾸기
if (x == current_time) :
if (c == 'D') :
current_dir = (current_dir + 1) % 4
if (c == 'L') :
current_dir = (current_dir - 1) % 4
if (len(change_time) > 0) :
x, c = change_time.pop(0)
# 만약 벽이나 자기자신의 몸과 부딪히면 게임이 끝난다.
if not ((0 <= snake_head[0] + direction[current_dir][0] < N) and (0 <= snake_head[1] + direction[current_dir][1] < N)) :
break
elif (arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] != 0
and arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] != -1):
break
apple = False
if (arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] == -1) :
apple = True
# 뱀의 머리를 방향대로 늘림.
arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] = (current_time + 1)
snake_head = [snake_head[0] + direction[current_dir][0], snake_head[1] + direction[current_dir][1]]
# 사과를 먹지 않았다면 꼬리 줄이기.
if not apple :
arr[snake_tail[0]][snake_tail[1]] = 0
minValue = 999999
tail_4 = [999999] * 4
idx = 0
for dd in direction :
if (0 <= snake_tail[0] + dd[0] < N and 0 <= snake_tail[1] + dd[1] < N) :
if ((arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] != 0) or (arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] != -1)) :
if (arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] == 0 or arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] == -1) :
idx += 1
continue
else :
tail_4[idx] = arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]]
idx += 1
else :
idx += 1
idx = tail_4.index(min(tail_4))
snake_tail = [snake_tail[0] + direction[idx][0], snake_tail[1] + direction[idx][1]]
print(current_time + 1)
참고 여부 : O
소요 시간 : 1시간
일단 주사위를 굴리는걸 구현한다는게 너무 어려웠다.
방법이 떠오르질 않아서 구글링을 하게 되었다. (세상엔 참 똑똑한 사람들이 많은 것 같다..)
방향을 돌려주는 매커니즘을 알아내서 굴린다음의 주사위를 업데이트 해주면 되는 것이었다.
이 방법을 알고나니 구현까진 수월했다. 그런데 "출력 초과"라는 결과가 나왔다.
난 디버거로 디버깅을 하는 편이라 코드 실수는 아닐 터였다..
한참을 살피다가 질문 게시판에도 올려보고, 챗 지피티랑 얘기도 해봤다.
앆! 발견했다. 지도에 주사위 아랫면을 업데이트 해줄 때 실수를 한 것이었다.
arr[y][x] = dice라고 써놓았다. 이를 arr[y][x] = dice[5]로 바꿔주니 바로 맞았다.
dice = [0] * 6
def turn(direct, y, x) :
global dice
global arr
a, b, c, d, e, f = dice
if (direct == 1) :
dice[0] = d
dice[2] = a
dice[3] = f
dice[5] = c
if (direct == 2) :
dice[0] = c
dice[2] = f
dice[3] = a
dice[5] = d
if (direct == 3) :
dice[0] = e
dice[1] = a
dice[4] = f
dice[5] = b
if (direct == 4) :
dice[0] = b
dice[1] = f
dice[4] = a
dice[5] = e
if (arr[y][x] != 0) :
dice[5] = arr[y][x]
arr[y][x] = 0
else :
arr[y][x] = dice[5]
n, m, x, y, k = map(int, input().split())
arr = []
for _ in range(n) :
arr.append(list(map(int, input().split())))
commend = list(map(int, input().split()))
current_x = y
current_y = x
direction = [[0, 1], [0, -1], [-1, 0], [1, 0]] # 동서북남 -> 오 왼 위 아래
for i in range(k) :
# 먼저 갈 수 있는 곳인지 판단. 아니라면 넘김
yy = direction[commend[i] - 1][0]
xx = direction[commend[i] - 1][1]
if not (0 <= current_x + xx < m and 0 <= current_y + yy < n) :
continue
current_y += yy
current_x += xx
turn(commend[i], current_y, current_x)
print(dice[0])
참고 여부 : X
소요 시간 : 36분
조건에 맞게 천천히 구현하면 되는 문제였다.
그런데.. 자가 수정을 거치는 바람에 시간이 좀 더 걸렸다. 반시계 방향을 회전한 다음 탐색을 하는 것인데, 현 방향부터 탐색을 하도록 하였다.
이 부분을 수정하니 바로 맞힐 수 있었다.
n, m = map(int, input().split())
r, c, d = map(int, input().split())
arr = []
for _ in range(n) :
arr.append(list(map(int, input().split())))
direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]
current_y = r
current_x = c
direction_idx = d
cnt = 0
while (True) :
if (arr[current_y][current_x] == 0) :
arr[current_y][current_x] = -1
cnt += 1
all_clean = True
# 주변의 4칸 탐색
for dd in range(1, 5, 1) :
yy, xx = direction[(direction_idx - dd) % 4]
if not (0 <= current_x + xx < m and 0 <= current_y + yy < n) :
continue
if (arr[current_y + yy][current_x + xx] == 0) :
direction_idx = (direction_idx - dd) % 4
current_y += yy
current_x += xx
all_clean = False
break
if all_clean :
yy, xx = direction[(direction_idx - 2) % 4]
if not (0 <= current_x + xx < m and 0 <= current_y + yy < n) :
continue
if (arr[current_y + yy][current_x + xx] != 1) :
current_y += yy
current_x += xx
elif (arr[current_y + yy][current_x + xx] == 1) :
break
print(cnt)
참고 여부 : X
소요 시간 : 3시간.. 넘게?
앞전에 주사위 문제를 풀었던 방식으로 풀면 되겠다 싶었다.
총 12개의 함수를 만들어주면 되겠다는 생각을 했는데..
내가 너무 안일했는지 처음부터 꼼꼼히 만들지 않아서 그걸 고치느라 꽤 고생했다.
이런 시뮬레이션 문제의 경우, 모든 경우의 수를 꼼꼼히 따지고 구현하는 것이 더 효율적일 것 같다는 생각이 들었다.
내가 실수했던 부분은 U+에서 돌릴때 배열을 뒤집어서 적용해줘야하는 것이다. 다른 경우에서도 마찬가지고..
단순한 예제만으로는 잡아낼 수가 없는 부분이었다.
아 그리고.. https://rubiks-cube-solver.com/fr/
이 사이트를 활용해서 문제를 풀면 편하다. 나는 한참뒤에 알아내서 시간이 너무 아까웠다.
근데 코테에서는 이런 페이지 사용을 허용하지 않을 것 같아서 손으로 풀어본게 나쁘지만은 않았다.
풀고 나서 보니 플레5 문제라서 아주 뿌듯했다. 내 첫 플레..
def turn_clock_reverse_way(idx) :
global cube
cube[idx] = [list(x) for x in zip(*cube[idx])][::-1]
def turn_clock_way(idx) :
global cube
cube[idx] = [list(x) for x in zip(*(cube[idx][::-1]))]
def l_minus() :
global cube
turn_clock_reverse_way(3)
o = [row[0] for row in cube[2]]
w = [row[0] for row in cube[0]]
r = [row[0] for row in cube[4]]
y = [row[0] for row in cube[5]]
for i in range(3) :
cube[2][i][0] = w[i]
cube[0][i][0] = r[i]
cube[4][i][0] = y[i]
cube[5][i][0] = o[i]
def l_plus() :
global cube
turn_clock_way(3)
o = [row[0] for row in cube[2]]
w = [row[0] for row in cube[0]]
r = [row[0] for row in cube[4]]
y = [row[0] for row in cube[5]]
for i in range(3) :
cube[4][i][0] = w[i]
cube[5][i][0] = r[i]
cube[2][i][0] = y[i]
cube[0][i][0] = o[i]
def r_minus() :
global cube
turn_clock_reverse_way(1)
o = [row[2] for row in cube[2]]
w = [row[2] for row in cube[0]]
r = [row[2] for row in cube[4]]
y = [row[2] for row in cube[5]]
for i in range(3) :
cube[4][i][2] = w[i]
cube[5][i][2] = r[i]
cube[2][i][2] = y[i]
cube[0][i][2] = o[i]
def r_plus() :
global cube
turn_clock_way(1)
o = [row[2] for row in cube[2]]
w = [row[2] for row in cube[0]]
r = [row[2] for row in cube[4]]
y = [row[2] for row in cube[5]]
for i in range(3) :
cube[2][i][2] = w[i]
cube[0][i][2] = r[i]
cube[4][i][2] = y[i]
cube[5][i][2] = o[i]
def b_plus() :
global cube
turn_clock_way(2)
w = cube[0][0]
g = cube[3][0][::-1]
y = cube[5][2][::-1]
b = cube[1][0]
cube[3][0] = w
cube[0][0] = b
cube[1][0] = y
cube[5][2] = g
def b_minus() :
global cube
turn_clock_reverse_way(2)
w = cube[0][0]
g = cube[3][0]
y = cube[5][2][::-1]
b = cube[1][0][::-1]
cube[3][0] = y
cube[0][0] = g
cube[1][0] = w
cube[5][2] = b
def u_plus() :
global cube
turn_clock_way(0)
r = cube[4][0]
o = cube[2][2]
b = [row[2] for row in cube[3]][::-1]
g = [row[0] for row in cube[1]][::-1]
for i in range(3) :
cube[1][i][0] = o[i]
cube[4][0] = g
for i in range(3) :
cube[3][i][2] = r[i]
cube[2][2] = b
def u_minus() :
global cube
turn_clock_reverse_way(0)
r = cube[4][0][::-1]
o = cube[2][2][::-1]
b = [row[2] for row in cube[3]]
g = [row[0] for row in cube[1]]
for i in range(3) :
cube[1][i][0] = r[i]
cube[2][2] = g
for i in range(3) :
cube[3][i][2] = o[i]
cube[4][0] = b
def f_plus() :
global cube
turn_clock_way(4)
b = cube[3][2]
w = cube[0][2]
g = cube[1][2][::-1]
y = cube[5][0][::-1]
cube[1][2] = w
cube[5][0] = g
cube[3][2] = y
cube[0][2] = b
def f_minus() :
global cube
turn_clock_reverse_way(4)
b = cube[3][2][::-1]
w = cube[0][2]
g = cube[1][2]
y = cube[5][0][::-1]
cube[1][2] = y
cube[5][0] = b
cube[3][2] = w
cube[0][2] = g
def d_plus() :
global cube
r = cube[4][2][::-1]
g = [row[0] for row in cube[3]]
b = [row[2] for row in cube[1]]
o = cube[2][0][::-1]
turn_clock_way(5)
for i in range(3) :
cube[1][i][2] = r[i]
cube[2][0] = b
for i in range(3) :
cube[3][i][0] = o[i]
cube[4][2] = g
def d_minus() :
global cube
r = cube[4][2]
g = [row[0] for row in cube[3]][::-1]
b = [row[2] for row in cube[1]][::-1]
o = cube[2][0]
turn_clock_reverse_way(5)
for i in range(3) :
cube[1][i][2] = o[i]
cube[4][2] = b
for i in range(3) :
cube[3][i][0] = r[i]
cube[2][0] = g
t = int(input())
for _ in range(t) :
n = int(input())
commend = list(input().split())
cube = [
[['w'] * 3 for _ in range(3)],
[['b'] * 3 for _ in range(3)],
[['o'] * 3 for _ in range(3)],
[['g'] * 3 for _ in range(3)],
[['r'] * 3 for _ in range(3)],
[['y'] * 3 for _ in range(3)],
]
for i in range(n) :
if commend[i] == 'L+' :
l_plus()
elif commend[i] == 'L-' :
l_minus()
elif commend[i] == 'R+' :
r_plus()
elif commend[i] == 'R-' :
r_minus()
elif commend[i] == 'U+' :
u_plus()
elif commend[i] == 'U-' :
u_minus()
elif commend[i] == 'D+' :
d_plus()
elif commend[i] == 'D-' :
d_minus()
elif commend[i] == 'F+' :
f_plus()
elif commend[i] == 'F-' :
f_minus()
elif commend[i] == 'B+' :
b_plus()
elif commend[i] == 'B-' :
b_minus()
for row in cube[0] :
print(*row, sep='')
"""
4
12
D+ L+ B+ U+ R+ F+ D- L- B- U- R- F-
12
D- L- B- U- R- F- D+ L+ B+ U+ R+ F+
12
F+ R+ U+ B+ L+ D+ F- R- U- B- L- D-
12
F- R- U- B- L- D- F+ R+ U+ B+ L+ D+
"""
주석 처리되어있는 예제가 아주 효과적으로 디버깅 가능하다.
이러한 예제를 짜는 것도 연습을 해야겠다.