[ 프로그래머스 / PYTHON ] 빛의 경로 사이클

yujeongkwon·2022년 9월 21일
0

프로그래머스 / PYTHON

목록 보기
61/77
post-custom-banner

문제 설명

빛의 경로 사이클

각 칸마다 S, L, 또는 R가 써져 있는 격자가 있습니다. 당신은 이 격자에서 빛을 쏘고자 합니다. 이 격자의 각 칸에는 다음과 같은 특이한 성질이 있습니다.

빛이 "S"가 써진 칸에 도달한 경우, 직진합니다.
빛이 "L"이 써진 칸에 도달한 경우, 좌회전을 합니다.
빛이 "R"이 써진 칸에 도달한 경우, 우회전을 합니다.
빛이 격자의 끝을 넘어갈 경우, 반대쪽 끝으로 다시 돌아옵니다. 예를 들어, 빛이 1행에서 행이 줄어드는 방향으로 이동할 경우, 같은 열의 반대쪽 끝 행으로 다시 돌아옵니다.
당신은 이 격자 내에서 빛이 이동할 수 있는 경로 사이클이 몇 개 있고, 각 사이클의 길이가 얼마인지 알고 싶습니다. 경로 사이클이란, 빛이 이동하는 순환 경로를 의미합니다.

예를 들어, 다음 그림은 격자 ["SL","LR"]에서 1행 1열에서 2행 1열 방향으로 빛을 쏠 경우, 해당 빛이 이동하는 경로 사이클을 표현한 것입니다.

ex1.png

이 격자에는 길이가 16인 사이클 1개가 있으며, 다른 사이클은 존재하지 않습니다.

격자의 정보를 나타내는 1차원 문자열 배열 grid가 매개변수로 주어집니다. 주어진 격자를 통해 만들어지는 빛의 경로 사이클의 모든 길이들을 배열에 담아 오름차순으로 정렬하여 return 하도록 solution 함수를 완성해주세요.

풀이 & Comment

알고리즘 자체는 생각보다 쉽다. [up,down,left,rigt] 를 각 칸 마다 적용시키는 것을 떠올리면 방문하지 않은 경로를 찾아 빛을 쏘면 된다. 그냥 구현 문제인데 생각보다 빡세다.

  1. 배열을 돌면서 방문하지 않은 곳 찾아 사이클 길이 구하기
  2. 빛이 격자의 끝을 넘어갈 경우, 반대쪽 끝으로 보정
  3. S, L, R 경우마다 빛의 사이클 지정

요 3가지가 핵심인 것 같은데 내가 아직 개찐따라 구현이 느린 건가 ^8^ 다시 풀어도 오래걸림 --

내코드

def solution(grid):
    global n,m
    answer = []
    n,m = len(grid),len(grid[0])
    coord = [[[0,0,0,0]for i in range(m)] for i in range(n)]
    
    for i in range(n):
        grid[i] = list(grid[i])
    
    for c in range(n):
        for r in range(m):
            for k in range(4):
                if coord[c][r][k] != 0:   continue
                cnt = cycle(coord,grid,c,r,k)-1
                answer.append(cnt)
                
    answer.sort()
    return answer


def cycle(coord,grid, i, j, out):
    cnt = 1
    while coord[i][j][out] != 1:
        coord[i][j][out] = cnt
        cnt += 1
        if grid[i][j] == "S": pass
        elif grid[i][j] == "L":
            if out == 0:   out = 2
            elif out == 1:   out = 3
            elif out == 2:   out = 1
            else:   out = 0
        else:
            if out == 0:   out = 3
            elif out == 1:   out = 2
            elif out == 2:   out = 0
            else:   out = 1
            
        i,j = route(out,i,j)
    return cnt


def route(out, i,j):
    if out == 0:   
        i -= 1
        if i < 0:   i = n-1
    elif out == 1:   
        i += 1
        if i >n -1 :    i = 0
    elif out == 2:   
        j -= 1
        if j < 0:   j = m-1
    else: 
        j += 1
        if j > m -1 :    j = 0
    return  i, j

옛날 코드 [up,down,left,rigt] -> (l r u d)순서만 다르고 똑같음

def route(route, i,j):
    if route == 0:   
        j -= 1
        if j < 0:   j = n-1
    elif route == 1:   
        j += 1
        if j > n -1 :    j = 0
    elif route == 2:   
        i -= 1
        if i < 0:   i = m-1
    else: 
        i += 1
        if i > m -1 :    i = 0
    return  i, j
    
def solution(grid):
    global n,m
    n,m = len(grid[0]), len(grid)
    answer = []
    visited = [[[0,0,0,0]for i in range(len(grid[0]))] for i in range(len(grid))]
    #l, r ,u , d 
    for _ in range(len(grid)):
        grid[_] = list(grid[_])
        
    for c in range(m):
        for r in range(n):
            for k in range(4):
                if visited[c][r][k] != 0:   continue
                count = 0
                i,j,out = c,r,k
                while visited[i][j][out] != 1:
                    visited[i][j][out] = count
                    count += 1
                    #경로설정
                    if grid[i][j] == "S": pass
                    elif grid[i][j] == "L":
                        if out == 0:   out = 3
                        elif out == 1:   out = 2
                        elif out == 2:   out = 0
                        else:   out = 1
                    else:
                        if out == 0:   out = 2
                        elif out == 1:   out = 3
                        elif out == 2:   out = 1
                        else:   out = 0 

                    i, j = route(out,i,j)
                answer.append(count-1)
    answer.sort()
    return answer
profile
인생 살자.
post-custom-banner

0개의 댓글