[Algorithm] 공원 산책

slight-snow·2023년 4월 6일
0

Algorithm

목록 보기
4/8
post-thumbnail

• 난이도

: Level.1

• 정답률

: 29%

• 문제:

: 공원 산책

• 설명:

: 지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양의 공원에서 로봇 강아지가 산책을 하려합니다. 산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.

  • ["방향 거리", "방향 거리" … ]

예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다. 로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.

  • 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
  • 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.

위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0), 우측 하단의 좌표는 (H - 1, W - 1) 입니다.

공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가 매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로 배열에 담아 return 하도록 solution 함수를 완성해주세요.

• 제한사항:

  • 3 ≤ park의 길이 ≤ 50
    • 3 ≤ park[i]의 길이 ≤ 50
      park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
           ‣ S : 시작 지점
           ‣ O : 이동 가능한 통로
           ‣ X : 장애물
      park는 직사각형 모양입니다.
  • 1 ≤ routes의 길이 ≤ 50
    • routes의 각 원소는 로봇 강아지가 수행할 명령어를 나타냅니다.
    • 로봇 강아지는 routes의 첫 번째 원소부터 순서대로 명령을 수행합니다.
    • routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
      ・ op는 다음 네 가지중 하나로 이루어져 있습니다.
           ‣ N : 북쪽으로 주어진 칸만큼 이동합니다.
           ‣ S : 남쪽으로 주어진 칸만큼 이동합니다.
           ‣ W : 서쪽으로 주어진 칸만큼 이동합니다.
           ‣ E : 동쪽으로 주어진 칸만큼 이동합니다.
      ・ 1 ≤ n ≤ 9

• 입출력 예:

parkroutesresult
["SOO","OOO","OOO"]["E 2","S 2","W 1"][2,1]
["SOO","OXX","OOO"]["E 2","S 2","W 1"][0,1]
["OSO","OOO","OXO","OOO"]["E 2","S 3","W 1"][0,0]

• 입출력 예 설명:

  • 입출력 예 #1
    입력된 명령대로 동쪽으로 2칸, 남쪽으로 2칸, 서쪽으로 1칸 이동하면
    [0,0] -> [0,2] -> [2,2] -> [2,1]이 됩니다.

  • 입출력 예 #2
    입력된 명령대로라면 동쪽으로 2칸, 남쪽으로 2칸, 서쪽으로 1칸 이동해야하지만 남쪽으로 2칸 이동할 때 장애물이 있는 칸을 지나기 때문에 해당 명령을 제외한 명령들만 따릅니다. 결과적으로는 [0,0] -> [0,2] -> [0,1]이 됩니다.

  • 입출력 예 #3
    처음 입력된 명령은 공원을 나가게 되고 두 번째로 입력된 명령 또한 장애물을 지나가게 되므로 두 입력은 제외한 세 번째 명령만 따르므로 결과는 다음과 같습니다.
    [0,1] -> [0,0]

• 작성 답안:

solution.js

function solution(park, routes) {
    //N(-1, 0), E(0, +1), S(+1, 0), W(0, -1) 
    let board = park.map((el) => el.split(""));
    //[["S", "O", "O"]
    // ["O", "O", "O"]
    // ["O", "O", "O"]]
    let X = board.indexOf(board.filter((el) => el.includes("S"))[0]);
    let Y = board.filter((el) => el.includes("S"))[0].findIndex((txt) => txt === "S")
    //X === 0, Y === 0
    
    for(i=0; i < routes.length; i++) {
        let direction = routes[i].split(" ")[0];
        let space = Number(routes[i].split(" ")[1]);
        
        if(direction === "E") {
            let backup = Y;
            for(j=1; j <= space; j++) {
                if(Y+1 <= board[0].length-1) {
                    if(board[X][Y+1] === "O" || board[X][Y+1] === "S") {
                        Y = Y + 1;
                    } else {
                        Y = backup;
                        break;
                    }
                } else {
                    Y = backup;
                    break;
                }
            }
        }
        if (direction === "W") {
            let backup = Y;
            for(j=1; j <= space; j++) {
                if(Y-1 >= 0) {
                    if(board[X][Y-1] === "O" || board[X][Y-1] === "S") {
                        Y = Y - 1;
                    } else {
                        Y = backup;
                        break;
                    }
                } else {
                    Y = backup;
                    break;
                }
            }
        }
        if (direction === "S") {
            let backup = X;
            for(j=1; j <= space; j++) {
                if(X+1 <= board.length-1) {
                    if(board[X+1][Y] === "O" || board[X+1][Y] === "S") {
                        X = X + 1;
                    } else {
                        X = backup;
                        break;
                    }
                } else {
                    X = backup;
                    break;
                }
            }
        }
        if (direction === "N") {
            let backup = X;
            for(j=1; j <= space; j++) {
                if(X-1 >= 0) {
                    if(board[X-1][Y] === "O" || board[X-1][Y] === "S") {
                        X = X - 1;
                    } else {
                        X = backup;
                        break;
                    }
                } else {
                    X = backup;
                    break;
                }
            }
        }
    }
    
    return [X, Y];
}

• 새로 작성한 답안:

solution.js

function solution(park, routes) {
    const board = park.map((el) => el.split(""));
    let X = board.indexOf(board.filter((el) => el.includes("S"))[0]);
    let Y = board.filter((el) => el.includes("S"))[0].findIndex((txt) => txt === "S")
    
    let check = (X, Y) => board[X][Y] === "O" || board[X][Y] === "S";
    
    for(i=0; i < routes.length; i++) {
        let direction = routes[i].split(" ")[0];
        let space = Number(routes[i].split(" ")[1]);
        
        if(direction === "E") {
            let backup = Y;
            for(j=1; j <= space; j++) {
                if(Y+1 <= board[0].length-1 && check(X, Y+1)) Y += 1;
                else { Y = backup; break; }
            }
        }
        if (direction === "W") {
            let backup = Y;
            for(j=1; j <= space; j++) {
                if(Y-1 >= 0 && check(X, Y-1)) Y -= 1;
                else { Y = backup; break; }
            }
        }
        if (direction === "S") {
            let backup = X;
            for(j=1; j <= space; j++) {
                if(X+1 <= board.length-1 && check(X+1, Y)) X += 1;
                else { X = backup; break; }
            }
        }
        if (direction === "N") {
            let backup = X;
            for(j=1; j <= space; j++) {
                if(X-1 >= 0 && check(X-1, Y)) X -= 1;
                else { X = backup; break; }
            }
        }
    }
    
    return [X, Y];
}


기존에 제출한 코드와 새로 작성한 코드를 비교해보았다.
기존 코드는 평균 0.4075ms, 새로 작성한 코드는 평균 0.3745ms 가 걸렸고,
기존에 0.5ms 를 넘어가는 테스트 케이스들이 없어졌다.
코드가 간결해진 것도 있지만 계산 시간도 단축되어 뿌듯하다 :)


이 문제를 푸는데만 거의 1-2시간 가까이 걸린 것 같다.

테스트 케이스는 금방 통과했지만,
제출 후 추가 채점에서 계속해서 런타임 에러가 발생했다.

질문하기 탭을 통해 다른 분들의 답변을 들어보니 index가
배열의 크기를 넘어가는 경우 런타임 에러가 발생한다고 하여,
배열에서 탐색할 때 index가 넘어가지 않도록 제한을 걸어줬더니
생각보다 금방 해결되었다 :)

허나, 보면 알겠지만 코드가 너무 길다...
다른 모범 답안을 참고하려고 했으나 다른 코드들 역시 너무 길었다.
아무래도 문제 자체가 짧은 코드로 접근하긴 어려웠던 걸까?

보통이라면 다른 답안을 아래에 작성해두겠지만
이번엔 예외적으로 내가 내 코드를 좀 더 최적화하고 수정해봐야겠다.
--> 계산 시간을 줄이는데 성공했다!

한 문제를 푸는데 몇 시간이 걸렸지만
어째서인지 오히려 기분 좋고 개운하다! 해냈다~ 라는 느낌 :D

계속 정진하도록 하겠다!

profile
주니어 개발자의 기억을 위한 기록 :)

0개의 댓글