코딩테스트

[ 프로그래머스 ] 방문 길이

Adose 2024. 12. 5. 13:52

📌요구 사항 정리

  • 게임 캐릭터가 지나간 길 중 캐릭터가 처음 걸어본 길이를 구해야 한다.
  • 중복 경로는 최종 길이에 포함하지 않는다.

 

📌 제약 조건

  • 문자형으로 주어지며, U, D, R, L 이외의 문자는 주어지지 않는다.
  • 길이는 500이하의 자연수이다.

 

📌 첫번째 풀이 문제 분석 ( 실패 )

❓ 처음 문제를 풀때, 그래프 생각을 못하고 단순히 방문 안했으면 0, 방문하면 1 이런식으로 했다.

하지만 이런식으로 구현하면 좌표 이동이 아닌, 그냥 좌표만 확인할 수 있으므로 좌표 이동을 확인할 수 없다.

예를들어 5,5 에서 Up을 하면 5,5 → 4,5 이게 1 이런식으로 되어야 하는데 단순히 좌표 위치를 0으로 선언하니까

Up 해야 할때 5,5 아니면 4.5 하나만 1(방문확인)로 변경이 된다.

—> 계속 해보다가 잘못됨을 느끼고 그래프로 다시 구현 했다.


  • 아래는 잘못된 문제 분석 
  • 표 사이즈는 -5 ~ 5 이기 때문에, 10 사이즈의 표를 만들어야 한다.
  • 표는 0으로 초기화하고, 해당 위치를 방문하게 되면 1로 변경해준다.
  • 해당되는 방향으로 이동한다.
  • 표의 값이 0이라면, 방문길이 +1 을 해주고 1이라면 넘긴다.
  • 방향 마다의 정보를 배열에 저장해야한다.
  • 현재 위치를 나타내는 정보를 배열에 저장해야한다.

❗ 실패 코드

 public int solution(String dirs) {
            char[] direction = dirs.toCharArray();
            int[][] gameBoard = new int[10][10];
            int[] currentLocation = {5, 5};
            int gameLength = 0;

            for (char location : direction) {
                int[] countLocation = getDirectionIfo(location);

                int newNum = currentLocation[0] + countLocation[0];
                int colNum = currentLocation[1] + countLocation[1];

                // 경계를 벗어나면 무시
                if (newNum < 0 || newNum >= 10 || colNum < 0 || colNum >= 10) {
                    continue;
                }

                // 새로운 위치 방문 여부 확인
                if (gameBoard[newNum][colNum] == 0) {
                    gameBoard[newNum][colNum] = 1; 
                    gameLength += 1;            
                }

                // 현재 위치 갱신
                currentLocation[0] = newNum;
                currentLocation[1] = colNum;
            }

            return gameLength;
        }

        public int[] getDirectionIfo(char dir) {
            Map<Character, int[]> directionInfo = new HashMap<>();

            final int[] U = {-1, 0};
            final int[] R = {0, 1};
            final int[] L = {0, -1};
            final int[] D = {1, 0};

            directionInfo.put('U', U);
            directionInfo.put('R', R);
            directionInfo.put('L', L);
            directionInfo.put('D', D);

            return directionInfo.get(dir);
        }

 

 

📌 두번째 풀이 문제 분석 ( 성공 )

  • HashSet<int [] > 를 사용하지 않는이유
    • HashSet은 배열의 참조를 비교하고, 값에는 참조하고 있지 않기 때문에 구분을 할 수 없다.
  • 현재 위치를 나타낼 수 있는 좌표를 저장해야한다. 
  • HashSet을 사용하여 중복을 허락하지 않고, x,y -> nx, ny 와 nx,ny -> x ,y 으로 저장할 수 있도록 한다.
    • x,y -> nx, ny 와 nx,ny -> x ,y 으로 하면 A -> B, B -> A 경로를 둘다 저장하여, 같던 길을 다시 갈 수 없도록 한다. 
  • 만약 설정한 범위 -5 ~ 5 를 넘는다면 넘기도록 한다. 좌표가 유효하지 않으면 경로 활동(=계산)에 추가하지 않는다.
private static final HashMap<Character, int[]> direction = new HashMap<>();

    public int solution(String dirs) {
        setDirectionIfo();
        char[] playerDirection = dirs.toCharArray();
        int x = 5;
        int y = 5;
        HashSet<int[]> gameLength = new HashSet<>();

        for (char location : playerDirection) {
            int offset[] = direction.get(location);
            int nx = x + offset[0];
            int ny = y + offset[1];

            if (validArea(nx, ny)) {
                continue;
            }

            gameLength.add(new int[]{x, y, nx, ny});
            gameLength.add(new int[]{nx, ny, x, y});

            x = nx;
            y = ny;

        }

        return gameLength.size() / 2;

    }

    private void setDirectionIfo() {
        direction.put('U', new int[]{-1, 0});
        direction.put('D', new int[]{1, 0});
        direction.put('R', new int[]{0, 1});
        direction.put('L', new int[]{0, -1});
    }

    private boolean validArea(int x, int y) {
        if (x < 0 || x > 10 || y < 0 || y > 10) {
            return true;
        }
        return false;
    }