대망의 초안발표 날이었다.
사실 지금까지 어디서든 발표를 전담해오기도 했고, 나름 자신도 있었어서 이번에도 발표 욕심이 있었다. 하지만 이번 프로젝트에서는 리더 대신 팀원으로 함께하기로 했기에, 다른 팀원들과 함께 발표 피드백과 PPT 준비에 최선을 다했다.
가이드라인을 준수해 최종발표처럼 팀원들과 함께 열심히 준비했고, 그 결과 의장님께 '발표의 스탠다드'라는 좋은 피드백을 받을 수 있었다. 다른 팀들보고 우리 팀의 발표를 기준으로 삼으라고 하셨기에, 매우 뿌듯했다.
나와 이단님의 무수한 발표 피드백과 코칭을 이겨내고 멋지게 발표를 마친 우리 리더 곤님께 정말 고마웠다.... 굿굿 :)
우리는 발표한 2가지 아이디어에 대해 모두 호평을 받았고, 그 중에 운영진 분들과 다른 정글 동기들에게 더 좋은 평가를 받은 프로젝트를 진행하기로 결정했다. 이후, 오늘도 한 잔 곁들이며 팀워크를 다졌다. 앞으로도 힘내자구 🏋🏻♂️
앞서 언급한대로, 오늘은 나만의무기 아이디어 초안을 발표하는 날이었다. 그래서 오후 2시에 본격적인 발표를 하기 전까지는 내내 PPT 수정 및 스크립트 보완에 힘썼다. PPT 제작은 조씨님과 이단님께서 초안을 만들어주시면, 내가 수정 및 보완하는 방식으로 진행했다. 이전 직장에서도 인턴 때부터 사장님 보고 들어가는 PPT를 만든 경험이 있어서, 크게 어렵지는 않았다.
원래는 오늘 구체적인 아이디어에 대해 적어보려 했는데, 생각해보니 어쨌거나 지금은 초안발표였고, 진짜 중요한 날은 1달 후에 있을 최종발표 날이다. 따라서 우리의 전반적인 아이디어와 PPT 구성은 아쉽지만 현재로써는 적지 않으려고 한다.
물론 의장님께서 발표는 이미 준비된 것 같다고 좋은 평을 내려주셨지만, 여기서 더 잘 준비할 수 있다. 우리는 다양한 가능성을 열어두고 개발에 몰두할 것이고, 팀의 발표와 PPT는 심지어 더 발전할 것이다. 팀 얼리버드, 가보자구~
오늘은 프로그래머스가 아니라 백준에서 진행했다.
로봇 청소기 라는 문제인데, 역시나 프로그래머스에 비해 불친절했다 , , ,
문제 설명이 다소 난해하여, 로봇 청소기는 다음과 작동한다 이하의 부분을 다음과 같이 재작성해보았다.
1. 현재 위치를 청소한다.
2. 현재 위치에서 다음을 반복하면서 인접한 칸을 탐색해 전진을 시도한다.
a. 왼쪽 방향으로 회전한다. 이때, 왼쪽은 현재 바라보는 방향을 기준으로 판단한다.
b. 현재 마주보는 칸이 아직 청소하지 않은 빈 공간이라면, 한 칸을 전진하고 1로 돌아간다.
c. 전진하지 못하고 연속으로 네 번 회전한 경우, 반복을 종료하고 3으로 간다.
3. 후진을 시도한다. 만약 후진하려는 칸이 벽이라면 작동을 멈춘다. 그렇지 않다면 한 칸 후진하고 1로 돌아간다.
문제 풀이도 위의 3가지 단계를 기준으로 진행하였다.
참고로 주어진 입력과 출력은 아래와 같았다.
문제를 보고나서, 우선 바라보는 방향에 따라서 탐색하는 칸이 달라진다는 것이 중요해보였다.
또한, 청소한 칸의 개수를 구해야하니까 한번 청소한 칸은 방문처리를 해주어야겠다고 생각했다. 그래야 후진하는 경우에 청소한 칸의 개수를 포함할지 말지를 결정할 수 있기 때문이다.
따라서, 우선 초기설정을 해주었다. 문제 조건에 따라 주어진 방향 d는 북(0)-동(1)-남(2)-서(3) 중 하나로 주어진다. 따라서 방향에 따라 어떤 순서에 따라 인접하는 칸들을 탐색해야할지 나누어 세팅해주었다.
import sys
input = sys.stdin.readline
N, M = map(int, input().strip().split())
r,c,d = map(int, input().strip().split()) # (r,c)는 칸의 좌표, d는 방향
Arr = [list(map(int, input().strip().split())) for _ in range(N)]
visited = [[False]*M for _ in range(N)]
direction_D = dict()
direction_D[0] = [(0,-1), (1,0), (0,1), (-1,0)] # 북쪽
direction_D[1] = [(-1,0), (0,-1), (1,0), (0,1)] # 동쪽
direction_D[2] = [(0,1), (-1,0), (0,-1), (1,0)] # 남쪽
direction_D[3] = [(1,0), (0,1), (-1,0), (0,-1)] # 서쪽
사실 하나의 리스트로도 가능하겠지만, 그렇게 하려면 회전할때마다 if문으로 현재 확인하는 인덱스가 0 미만 혹은 4 이상이 되는지를 확인하고 재조정해주는 작업이 필요해서 비효율적이라고 생각했다.
이렇게 초기세팅을 해준 후에, 로봇청소기가 작동할 수 있는 루프를 구성해주려다보니 한 가지 고민이 생겼다. 바로 방문처리를 어느 지점에서 해줄 것인지에 대한 것이었다. 처음에는 루프가 돌때마다 방문처리를 해주려했다. 하지만 그렇게 하면 중복으로 방문처리를 하게 되거나, 혹은 루프가 돌때마다 현재 방문한 칸이 청소를 이미 한 칸인지 아닌지를 판별해야 했다. 따라서, 루프 내에서 방문할 수 있는 인접한 칸을 찾는 순간에 청소 & 이동 & 방문처리를 진행해주도록 하였다.
이런 로직에 따라, 문제에서 주어지는 첫 칸은 무조건 청소하고 시작하게 되므로 방문처리를 하고, 청소하는 칸을 카운트하는데에 미리 포함해주었다. 그리고, 현재 바라보는 방향에 따라서 어떤 순서로 탐색해주어야할지 찾아주었다. 참고로 주어진 d는 시계방향 순으로 숫자가 지정되었는데, 왼쪽 방향으로 돌게되면 반시계 방향으로 돌게된다. 따라서, 한번 회전할때마다 d를 -1 해주도록 하는 방법을 선택했다.
이와 같이 구성한 로봇청소기 작동 루프를 재작성한 3단계에 따라 정리하자면 다음과 같다.
visited[r][c] = True
cnt = 1
while True:
# 단계 2. 현재 위치에서 다음을 반복하며, 인접한 칸을 탐색한다.
if d < 0:
d += 4
now_rotate_D = direction_D[d]
for dr, dc in now_rotate_D:
# 단계 2-a. 왼쪽 방향으로 회전한다. 이때, 왼쪽은 현재 바라보는 방향을 기준으로 판단한다
d -= 1
nr, nc = r + dr, c + dc
# 단계 2-b. 현재 마주보는 칸이 아직 청소하지 않은 빈 공간이라면, 한 칸을 전진하고 1로 돌아가서 현재 위치를 청소한다.
if 0 <= nr < N and 0 <= nc < M and not Arr[nr][nc] and not visited[nr][nc]:
r,c = nr,nc
cnt += 1
visited[nr][nc] = True
break
else:
# 단계 2-c. 전진하지 못하고 연속 네 번 회전한 경우, 반복을 종료하고 3으로 간다
d += 4 # 다시 원래 d로 돌려줌(d-4가 되도록 전진에 실패하여 else로 넘어왔으니)
# 단계 3. 후진을 시도한다
dr, dc = now_rotate_D[1]
nr, nc = r + dr, c + dc
# 단계 3. 뒷칸이 벽이라면 청소기 작동이 종료됨.
if Arr[nr][nc]: break
# 단계 3. 뒷칸이 벽이 아니라면 후진하고, 단계 1로 돌아가 현재 위치를 청소한다.
r, c = nr, nc
if not visited[nr][nc]:
# 처음 청소하는 칸이라면 cnt에 포함해주고 방문처리한다.
visited[nr][nc] = True
cnt += 1
이때, 또 하나 고려한 점은 3번째 단계에서 후진할 때, 그 위치가 이미 청소한 칸이었을수도 있다는 것이다.
후진은 하되 이미 청소를 했으니, 청소하는 칸을 셀때 중복해서 세면 안된다는 것이다:)
제출 당시에 최종 코드는 다음과 같이 구성해서 제출했다!
# 각각의 칸은 벽이거나 빈칸이다..
# 청소기는 바라보는 방향이 있음. (동,서,남,북)
# (r,c) => 지도 북쪽에서부터 r번째, 서쪽에서부터 c번째
import sys
input = sys.stdin.readline
N, M = map(int, input().strip().split())
r,c,d = map(int, input().strip().split()) # (r,c)는 칸의 좌표, d는 방향
Arr = [list(map(int, input().strip().split())) for _ in range(N)]
visited = [[False]*M for _ in range(N)]
direction_D = dict()
direction_D[0] = [(0,-1), (1,0), (0,1), (-1,0)] # 북쪽
direction_D[1] = [(-1,0), (0,-1), (1,0), (0,1)] # 동쪽
direction_D[2] = [(0,1), (-1,0), (0,-1), (1,0)] # 남쪽
direction_D[3] = [(1,0), (0,1), (-1,0), (0,-1)] # 서쪽
visited[r][c] = True
cnt = 1
while True:
# 단계 2. 현재 위치에서 다음을 반복하며, 인접한 칸을 탐색한다.
if d < 0:
d += 4
now_rotate_D = direction_D[d]
for dr, dc in now_rotate_D:
d -= 1
nr, nc = r+dr, c+dc
if 0<=nr<N and 0<=nc<M and not Arr[nr][nc] and not visited[nr][nc]:
r,c = nr,nc
cnt += 1
visited[nr][nc] = True # 단계 1. 현재 위치를 청소한다
break
else:
d += 4 # 다시 원래 d로 돌려줌
dr, dc = now_rotate_D[1]
nr, nc = r+dr, c+dc
r, c = nr, nc
# 뒷칸이 벽이라면 청소기 작동이 종료됨.
if Arr[nr][nc]:
break
if not visited[nr][nc]:
visited[nr][nc] = True # 단계 1. 현재 위치를 청소한다
cnt += 1
print(cnt)
오늘 하루도 알차게 보냈다:)
내일도 화이팅!