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

butterbeetle·2023년 5월 3일
0

코딩테스트

목록 보기
120/132
post-thumbnail

문제설명

지나다니는 길을 '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]

내 풀이

function solution(park, routes) {
    /* 지도 크기 */
    const W = park[0].length
    const H = park.length
    console.log("H",H,"W",W)
    
    /* 시작지점 찾기 */
    const coordinate = park.join("")
    const start = coordinate.indexOf("S")
    const startCoordinate = [Math.floor(start/H),start%H]
    console.log("시작위치",startCoordinate)
    
    /* 이동 */
    const movement = (h,w,step,direction) => {
        if(direction === "N"){ 
            if( (h-step) < 0   || coordinate[ (h-step)*W + w ] === "X") return true
            else return false
        }else if(direction === "S"){ 
            if( (h+step) >= H || coordinate[ (h+step)*W + w ] === "X") return true
            else return false
        }else if(direction === "W"){ 
            if( (w-step) < 0   || coordinate[ h*W + (w-step) ] === "X") return true
            else return false
        }else if(direction === "E"){ 
            if( (w+step) >= W || coordinate[ h*W + (w+step) ] === "X") return true
            else return false
        } 
    }
    
    /* 답 */
    const ans = routes.reduce(([h,w],cur)=>{
        const step = +cur.at(-1)
        const direction = cur.at(0)
        
        for(let i=1; i<=step; i++){
            const state = movement(h,w,i,direction)
            if(state) return [h,w]
        }
        
        if(direction === "N")      return [h-step,w]
        else if(direction === "S") return [h+step,w]
        else if(direction === "W") return [h,w-step]
        else if(direction === "E") return [h,w+step]
         
    },startCoordinate);
    
    return ans
}

지도 크기를 구하고 시작지점을 찾고 이동할 방향에 따라 로직을 작성했는데
내 방식으로 하면 방향에따라 계산하는게 2번이기 때문에 깔끔하지 못한것 같다.

밑에는 좋아요 제일 많이 받은분의 풀이인데
방향을 객체로 선언해서 쓰는건 생각 못했는데
내 코드길이의 1/2밖에 안나오니 참 좋은 것 같다

function solution(park, routes) {
        const dirs = { E: [0, 1], W: [0, -1], S: [1, 0], N: [-1, 0] };
        let [x, y] = [0, 0];
        for (let i = 0; i < park.length; i++) {
          if (park[i].includes('S')) {
            [x, y] = [i, park[i].indexOf('S')];
            break;
          }
        }

        routes.forEach((route) => {
          const [r, n] = route.split(' ');
          let [nx, ny] = [x, y];
          let cnt = 0;
          while (cnt < n) {
            [nx, ny] = [nx + dirs[r][0], ny + dirs[r][1]];
            if (!park[nx] || !park[nx][ny] || park[nx][ny] === 'X') break;
            cnt++;
          }
          if (cnt == n) [x, y] = [nx, ny];
        });
        return [x, y];
      }
profile
멍청이

0개의 댓글