알고리즘/프로그래머스

프로그래머스 LV2. 빛의 경로 사이클 (자바)

reumiii 2022. 5. 1. 21:35

🍀 문제

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

  • 빛이 "S"가 써진 칸에 도달한 경우, 직진합니다.
  • 빛이 "L"이 써진 칸에 도달한 경우, 좌회전을 합니다.
  • 빛이 "R"이 써진 칸에 도달한 경우, 우회전을 합니다.
  • 빛이 격자의 끝을 넘어갈 경우, 반대쪽 끝으로 다시 돌아옵니다. 예를 들어, 빛이 1행에서 행이 줄어드는 방향으로 이동할 경우, 같은 열의 반대쪽 끝 행으로 다시 돌아옵니다.

당신은 이 격자 내에서 빛이 이동할 수 있는 경로 사이클이 몇 개 있고, 각 사이클의 길이가 얼마인지 알고 싶습니다. 경로 사이클이란, 빛이 이동하는 순환 경로를 의미합니다.

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

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

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

 

제한사항

  • 1 ≤ grid의 길이 ≤ 500
    • 1 ≤ grid의 각 문자열의 길이 ≤ 500
    • grid의 모든 문자열의 길이는 서로 같습니다.
    • grid의 모든 문자열은 'L', 'R', 'S'로 이루어져 있습니다.

 

입출력 예

grid result
["SL","LR"] [16]
["S"] [1,1,1,1]
["R","R"] [4,4]

 

 

코딩테스트 연습 - 빛의 경로 사이클 | 프로그래머스 (programmers.co.kr)

 

코딩테스트 연습 - 빛의 경로 사이클

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

programmers.co.kr

 

 

😊 나의 코드

import java.util.*;
class Solution {
    public int[] solution(String[] grid) {
        int dir[][] = {{0,1}, {0,-1}, {1,0}, {-1,0}}; //오,왼,아래,위
        int lengthX = grid.length;
        int lengthY = grid[0].length();
        ArrayList<Integer> list = new ArrayList<Integer>();
        boolean[][][] checked = new boolean[lengthX ][lengthY][dir.length];

        for(int i=0; i<lengthX; i++) {
            for(int j=0; j<lengthY; j++) {
                int pos[] = {i,j};

                for(int k=0; k<dir.length; k++) {
                    int lightDir = k;
                    int cnt = 0; // 사이클 길이
                    do {
                        if(checked[pos[0]][pos[1]][lightDir]) {
                            cnt=0;
                            break;
                        }
                        checked[pos[0]][pos[1]][lightDir] = true;
                        cnt++;
                        char direction = grid[pos[0]].charAt(pos[1]); // 현재 칸의 방향
                        lightDir = trans(direction,lightDir); // 빛의 방향

                        pos[0] = movePos(pos[0], dir[lightDir][0], lengthX);
                        pos[1] =movePos(pos[1], dir[lightDir][1], lengthY);

                    }while(!(pos[0]==i && pos[1]==j && lightDir==k));

                    if(cnt>0) {
                        list.add(cnt);
                    }
                }
            }
        }

        Collections.sort(list);
        int[] answer = new int[list.size()];
        for(int i=0; i <list.size(); i++) {
            answer[i] = list.get(i); 
        }
        return answer;
    }

    public int trans(char direction , int light) { //빛의 방향 변환
        if(direction=='R') {
            if(light==0) {
                light = 2;
            }else if(light==1){
                light = 3;
            }else if(light==2){
                light = 1;
            }else {
                light = 0;
            }
        }else if(direction=='L') {
            if(light==0) {
                light = 3;
            }else if(light==1){
                light = 2;
            }else if(light==2){
                light = 0;
            }else {
                light = 1;
            }
        }

        return light;
    }

    public int movePos(int pos, int move , int max){ //빛의 방향에 따른 칸 이동
        pos = pos + move;
        if(pos < 0) {
            return max-1;
        }else if(pos >= max) {
            return 0;
        }
        return pos;
    }
}

 

테스트 케이스는 다 맞았는데, 실행하면 다 실패가 떠서 

왜그런가 했는데

칸 (0,0)에서 시작하는 사이클만 계산해서 오답이었다.

(0,0)칸 말고 모든 칸에서 모든 방향(상,하,좌,우)으로 길이를 확인해야 했다.

 

그래서 1. 이중 for문으로 모든 칸을 확인하고

2. 그 안에 for문 하나로 4가지 방향으로 사이클을 확인했다. (총 3개의 for문)

3. boolean[x칸][y칸][방향] checked 변수로 중복된 사이클인지 구분했다.

 

- trans 함수는 칸의 R,L,S 방향에 따른 바뀐 빛의 방향을 리턴한다.

- 마지막 anwer는 오름차순으로 정렬 후 리턴한다.