PS/9oormthon Challenge

구름톤 챌린지 Week 2 - Day 10

_빌런 2023. 8. 25. 21:59

https://level.goorm.io/exam/195692/gamejam/quiz/1

전형적인 '구현' 문제다. 구글 코딩 테스트에서도 이와 유사한 느낌으로 나온 적이 있었다.

문제를 읽고, 조건들을 살피고, 정해진 방법 없이 말그대로 구현하는 문제다.

 

많은 사람들이 문제를 해석함에 있어서 곤혹을 치뤘다.

그 이유는 구름에서 문제 조건을 애매하게 작성해두었기 때문이다.

물론 시간이 지나 정말 많은 사람들이 의견을 달아주셨고, 그제서 문제 수정을 해줬다.

민심은 싫어요를 보고 알 수 있다 생각한다.

 

# ---------- 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)으로 좌우 이동이 가능하다.

위와 같이 범위 밖으로 벗어났을 때, 반대쪽으로 나오는 문제에서 유용하니 한 번 익혀두는 것도 좋다.