구름톤 챌린지 Week 2 - Day 10
전형적인 '구현' 문제다. 구글 코딩 테스트에서도 이와 유사한 느낌으로 나온 적이 있었다.
문제를 읽고, 조건들을 살피고, 정해진 방법 없이 말그대로 구현하는 문제다.
많은 사람들이 문제를 해석함에 있어서 곤혹을 치뤘다.
그 이유는 구름에서 문제 조건을 애매하게 작성해두었기 때문이다.
물론 시간이 지나 정말 많은 사람들이 의견을 달아주셨고, 그제서 문제 수정을 해줬다.
민심은 싫어요를 보고 알 수 있다 생각한다.
# ---------- Function ----------
def clear():
global visited
visited = [[0]*length for _ in range(length)]
def GameJam(player: list):
global visited
dr = ["U", "D", "L", "R"]
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
x, y = player
x -= 1; y -= 1
visited[x][y] = 1
while True:
move, cmd = board[x][y][0:-1], board[x][y][-1]
move, cmd = int(move), dr.index(cmd)
nx, ny = dx[cmd], dy[cmd]
for _ in range(move):
x += nx; y += ny
if x < 0: x = length-1
elif x >= length: x = 0
elif y < 0: y = length-1
elif y >= length: y = 0
if visited[x][y] == 0:
visited[x][y] = 1
else:
return sum(map(sum, visited))
# ---------- Main ----------
visited = []
length = int(input())
goorm = map(int, input().split())
player = map(int, input().split())
board = [list(input().rstrip().split()) for _ in range(length)]
clear()
goorm_result = GameJam(goorm)
clear()
player_result = GameJam(player)
if goorm_result > player_result: print("goorm", goorm_result)
else: print("player", player_result)
clear() 함수는 방문 여부의 모든 요소를 0으로 초기화하는 함수다.
GameJam() 함수는 플레이어의 따라 점수를 계산해주는 함수다.
# ---------- Main ----------
visited = []
length = int(input())
goorm = map(int, input().split())
player = map(int, input().split())
board = [list(input().rstrip().split()) for _ in range(length)]
clear()
goorm_result = GameJam(goorm)
clear()
player_result = GameJam(player)
if goorm_result > player_result: print("goorm", goorm_result)
else: print("player", player_result)
Main 코드부터 간단하게 살펴보자. 대부분 입력과 함수 동작이라 크게 설명할 부분은 없다.
visited를 선언하고, 문제에서 주어진 입력들을 전부 받는다.
clear(), GameJam(), clear(), GameJam()으로 goorm과 player의 점수를 계산한다.
그리고 점수가 더 큰 쪽의 이름과 점수를 출력해주는 코드이다.
# ---------- Function ----------
def clear():
global visited
visited = [[0]*length for _ in range(length)]
clear() 함수는 visited를 global로 받아와 수정해준다.
가로 세로 length 길이만큼 0으로 초기화한 2차원 배열을 선언한다.
# ---------- Function ----------
def GameJam(player: list):
global visited
dr = ["U", "D", "L", "R"]
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
GameJam에서도 visited를 global로 수정할 수 있게 선언한다.
dx와 dy는 이동 방향을 결정할 list들이다.
dr은 사용자가 이동함에 따라, 방향을 정해주는 list다. index로 dx, dy를 정해준다.
x, y = player
x -= 1; y -= 1
visited[x][y] = 1
player(여기서 player는 goorm 혹은 player의 입력을 뜻한다.)
x와 y는 1부터 시작이기에, 1 값을 빼준 좌표를 player의 위치로 잡아준다.
그리고 visited[x][y]를 방문 체크(1)한다.
while True:
move, cmd = board[x][y][0:-1], board[x][y][-1]
move, cmd = int(move), dr.index(cmd)
nx, ny = dx[cmd], dy[cmd]
특별한 조건없이 계속해서 GameJam을 진행하다가, 특정 조건을 만족해야 빠져나온다.
따라서 while True로 계속 실행해준다. 이때 무한 루프에 빠지지 않게 조심하자.
move, cmd를 각각 보드게임판에서 가져온다.
이때 조심할 것은, 예제 입력이 한 자리 숫자와 한 자리 문자여서 그대로 코딩하면 안 된다.
각 숫자는 N보다 작거나 같고, N은 최대 200, 세 자리 숫자까지 가능하다.
보드게임판(board[x][y])에서 첫 번째 값([0])이 아닌, 처음부터 마지막 직전([:-1])까지 값을 가져와야 한다.
그리고 이동 방향은 두 번째 값([1])이 아닌, 마지막 값([-1])을 가져와야 한다.
move로 가져온 숫자는 문자이기에 int로 형변환을 진행한다.
cmd로 가져온 이동 방향은 U, D, L, R 중 하나기에, dr에서 index로 dx dy에 맞게 바꿔준다.
그리고 계속해서 같은 방향으로 이동해줘야 하기에, nx ny에 dx[cmd], dy[cmd] 값을 넣어서 더해주게끔 한다.
for _ in range(move):
x += nx; y += ny
if x < 0: x = length-1
elif x >= length: x = 0
elif y < 0: y = length-1
elif y >= length: y = 0
if visited[x][y] == 0:
visited[x][y] = 1
else:
return sum(map(sum, visited))
move만큼 한 칸 한 칸 전진한다.
이때 범위를 벗어났다면, 반대쪽으로 돌아오게 하는 것을 잊지 말자.
방문하지 않았다면(visited[x][y] == 0) 방문하고, 방문했다면 그대로 종료하고 visited의 값을 모두 더하면 된다.
visited는 0 아니면 1 값이 들어가있기 때문에, 모두 더한 값이 방문한 칸의 개수와 동일하다.
if와 elif로 짜는 것이 더럽고, 조금 더 직관적으로 짜고 싶다면 deque() 자료구조를 이용할 수 있다.
MOVE라는 2차원의 deque([ deque([]), deque([]), ..., deque([]) ])를 선언했다고 해보자.
그럼 deque.rotate(N)으로 위아래 이동이 가능하고, deque[i].rotate(N)으로 좌우 이동이 가능하다.
위와 같이 범위 밖으로 벗어났을 때, 반대쪽으로 나오는 문제에서 유용하니 한 번 익혀두는 것도 좋다.