본문 바로가기

알고리즘/구현

[프로그래머스] lv1 공원 산책 java [구현][엄탱]

728x90

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/172928

 

프로그래머스

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

programmers.co.kr

문제 설명

문제는 길기 때문에 링크를 통해서 보는 것을 추천한다.

요약하자면 로봇 강아지를 이동하라는 만큼 이동한 후에 최종 지점을 출력하면 된다.

단, 이동하는데 공원을 벗어나거나 장애물이 있으면 해당 명령은 무시하면 된다.

해설

해당 문제는 따로 해설이 필요하지 않고, 문제 설명대로 코드를 작성하면 된다.

문제 풀이

우선 무작정 설명에 나와있는 거 그대로 코드를 작성한 방식과 해당 방식을 리펙토링 해서 풀어낸 방식 두 가지가 있다.

이번 문제에서 가장 핵심은 리펙토링 하는 부분에서 이동 방향을 동{0, 1}, 서{0, -1}, 남{1, 0}, 북{-1, 0}으로 직접 만든 게 핵심이다.

방향이 들어가는 문제들은 아래와 같이 좌표를 미리 만들어 두고 하는 게 좋다.

// 순서대로 동, 서, 남, 북
int dx = {0, 0, 1, -1};
int dy = {1, -1, 0, 0};

안 그러면 코드가 복잡해지고 그러다 보면 쉬운 문제도 실수가 많아져 시간만 잡아먹고 문제도 틀릴 수 있다. 

아래가 복잡해지는 코드의 예시일 수 있겠다.

 

1. 리펙토링 전

엄청 복잡하다.. 문제를 풀고 나서도 런타임 에러가 발생하는데.. 왜 발생하는지 찾는데만 많은 시간을 소비했다.

근데 찾고 보면 정말 간단한 부분을 실수하는 경우가 많다.

이렇게 복잡한 코드를 방향을 미리 지정해서 코드를 짜면 간단해진다.

class Solution {
    public int[] solution(String[] park, String[] routes) {
        int[] start = getStartPosition(park);

        int H = park.length;
        int W = park[0].length();

        for (String route: routes) {
            char direction = route.charAt(0);
            int num = route.charAt(2) - '0';

            if (direction == 'E') {
                if (start[1] + num > W - 1) {
                    continue;
                }

                start[1] += num;

                for (int j = start[1] - num + 1; j <= start[1]; j++) {
                    if (park[start[0]].charAt(j) == 'X') {
                        start[1] -= num;
                        break;
                    };
                }
            } else if (direction == 'W') {
                if (start[1] - num < 0) {
                    continue;
                }

                start[1] -= num;

                for (int j = start[1]; j <= start[1] + num; j++) {
                    if (park[start[0]].charAt(j) == 'X') {
                        start[1] += num;
                        break;
                    };
                }
            } else if (direction == 'S') {
                if (start[0] + num > H - 1) {
                    continue;
                }

                start[0] += num;

                for (int j = start[0] - num; j <= start[0]; j++) {
                    if (park[j].charAt(start[1]) == 'X') {
                        start[0] -= num;
                        break;
                    };
                }
            } else {
                if (start[0] - num < 0) {
                    continue;
                }

                start[0] -= num;

                for (int j = start[0]; j <= start[0] + num; j++) {
                    if (park[j].charAt(start[1]) == 'X') {
                        start[0] += num;
                        break;
                    };
                }
            }
        }

        return start;
    }

    private int[] getStartPosition(String[] park) {
        for (int i = 0; i < park.length; i++) {
            for (int j = 0; j < park[i].length(); j++) {
                char c = park[i].charAt(j);

                if ('S' == c) {
                    return new int[]{i, j};
                }
            }
        }

        return new int[]{0, 0};
    }
}

2. 리펙토링 후

물론 이것도 짧진 않지만 if문 안에 if문 그 안에 for문 그 안에 if문 이런 식으로 복잡한 코드보다는 깔끔해진다.

 

import java.util.*;

class Solution {
    public int[] solution(String[] park, String[] routes) {
        int[] start = getStartPosition(park);
        
        Map<Character, int[]> map = new HashMap<>();
        
        map.put('E', new int[]{0, 1});
        map.put('W', new int[]{0, -1});
        map.put('S', new int[]{1, 0});
        map.put('N', new int[]{-1, 0});
        
        for (String route: routes) {
            char direction = route.charAt(0);
            int moveCount = route.charAt(2) - '0';
            
            int[] dxdy = map.get(direction);
            
            int dx = dxdy[0];
            int dy = dxdy[1];
            
            int curX = start[0];
            int curY = start[1];
            
            boolean isOk = true;
            
            for (int i = 0; i < moveCount; i++) {
                curX += dx;
                curY += dy;
                
                if (curX < 0 || curY < 0 || curX > park.length - 1 || curY > park[0].length() - 1) {
                    isOk = false;
                    break;
                }
                
                if (park[curX].charAt(curY) == 'X') {
                    isOk = false;
                    break;
                }
            }
            
            if (isOk) {
                start[0] = curX;
                start[1] = curY;
            }
        }

        return start;
    }

    private int[] getStartPosition(String[] park) {
        for (int i = 0; i < park.length; i++) {
            for (int j = 0; j < park[i].length(); j++) {
                char c = park[i].charAt(j);

                if ('S' == c) {
                    return new int[]{i, j};
                }
            }
        }

        return new int[]{0, 0};
    }
}
728x90