마이의 개발 블로그

[프로그래머스] 공원 산책 (Java) 본문

코딩테스트/프로그래머스

[프로그래머스] 공원 산책 (Java)

개발자마이 2023. 4. 20. 20:45
반응형
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

접근 방식

단순 구현 문제로 금방 해결할 줄 알았으나 케이스 예외처리를 제대로 해주지 못해 애를 먹었던 문제이다. 문제에도 적혀있듯 이동 명령을 수행하며 범위를 벗어나는지 여부와 지도에서 'X'로 막혀있는지 여부의 두 가지 조건만 체크하면 되는 문제인데, 동서남북 각 방향에 따른 예외 처리와 반복문 처리가 각각 달라 길게 작성된 코드를 짧게 처리하는데 애를 먹었다. 더 짧게 하고싶은데 다른 사람들 코드도 길이가 비슷한 걸 보니 어쩔 수 없는 문제였던 것 같기도 하다.

로직 설명

- 시작점 찾기: 문자열 "S"를 포함한 문자열의 x값, y값 저장

- routes 배열의 각 이동명령 move를 탐색하며:

1) move로부터 방향(dir)과 숫자(num) 추출하기

2) 서, 북인 경우 num에 -1 곱하기

3) 동, 서인 경우 x축 이동, 남, 북인 경우 y축 이동한 값을 postX, postY 변수에 저장하기 (기존 x, y는 변화없음)

4) 조건1: 지도 범위를 벗어난 경우 명령 무시 (continue)

5) 조건2: 이동할 경로에 'X'표가 있는 경우 명령 무시. x와 postX, y와 postY 간의 경로를 탐색하며 'X'표시가 있는 경우 isBlocked = true 표기 후 루프 종료 (x축과 y축은 각각 다른 루프로 체크)

6) 장애물이 없으면(isBlocked가 false이면) x와 y에 각각 postX, postY 대입하기

- 결과 반환 (y, x 순으로 배열 생성)

Note

- 주의해야할 점은 x와 postX, y와 postY 사이의 경로를 탐색함에 있어 기존과 post 둘 중 어떤 숫자가 더 크냐에 따라 루프의 시작점이 달라져야한다는 점이다. 이 부분을 캐치하지 못해 몇몇 케이스에서 오류가 났고 결국 두 개의 루프문 안에 삼항연산자를 사용해 매번 작은 값부터 큰 값으로 경로가 이동하도록 했다. 그러나 이렇게 처리할 경우 굳이 체크 안 해도 되는 시작 좌표를 한 번 더 점검하게 될 수도 있는 단점이 있는데 코드 몇 줄 늘리는 것보단 가독성이 더 나을 것 같아 그대로 두기로 했다. 

class Solution {
    public int[] solution(String[] park, String[] routes) {
        int x = 0, y = 0;
        
        for(String str: park){
            if(str.contains("S")){
               x = str.indexOf("S");
               break;
            }
            y++;
        }

        for(String move : routes){
            String[] arr = move.split(" ");
            Character dir = arr[0].charAt(0);
            int num = Integer.parseInt(arr[1]);
            int postX = x, postY = y;
            
            num *= (dir == 'W' || dir == 'N') ? -1 : 1;
            if(dir == 'E' || dir == 'W'){
                postX += num;
            }else{
                postY += num;
            }
            
            if(postX < 0 || postX >= park[0].length() || postY < 0 || postY >= park.length){
                continue;
            }
            
            Boolean isBlocked = false;
            
            for(int i = (x < postX ? x : postX); i <= (x < postX ? postX : x); i++){
                if(park[y].charAt(i) == 'X'){
                    isBlocked = true;
                    break;
                }   
            }
            
            for(int j = (y < postY ? y : postY); j <= (y < postY ? postY : y); j++){
                if(park[j].charAt(x) == 'X'){
                    isBlocked = true;
                    break;
                }
            }
            
            if(!isBlocked){
                x = postX;
                y = postY;    
            }
        }
        return new int[] {y, x};
    }
}
반응형
Comments