[Programmers] 미로 탈출 - JavaScript

Joosi_Cool·2023년 5월 4일
2

Programmers

목록 보기
77/98
post-thumbnail

문제설명

1 x 1 크기의 칸들로 이루어진 직사각형 격자 형태의 미로에서 탈출하려고 합니다. 각 칸은 통로 또는 벽으로 구성되어 있으며, 벽으로 된 칸은 지나갈 수 없고 통로로 된 칸으로만 이동할 수 있습니다. 통로들 중 한 칸에는 미로를 빠져나가는 문이 있는데, 이 문은 레버를 당겨서만 열 수 있습니다. 레버 또한 통로들 중 한 칸에 있습니다. 따라서, 출발 지점에서 먼저 레버가 있는 칸으로 이동하여 레버를 당긴 후 미로를 빠져나가는 문이 있는 칸으로 이동하면 됩니다. 이때 아직 레버를 당기지 않았더라도 출구가 있는 칸을 지나갈 수 있습니다. 미로에서 한 칸을 이동하는데 1초가 걸린다고 할 때, 최대한 빠르게 미로를 빠져나가는데 걸리는 시간을 구하려 합니다.

미로를 나타낸 문자열 배열 maps가 매개변수로 주어질 때, 미로를 탈출하는데 필요한 최소 시간을 return 하는 solution 함수를 완성해주세요. 만약, 탈출할 수 없다면 -1을 return 해주세요.


제한사항
  • 5 ≤ maps의 길이 ≤ 100
    • 5 ≤ maps[i]의 길이 ≤ 100
    • maps[i]는 다음 5개의 문자들로만 이루어져 있습니다.
      • S : 시작 지점
      • E : 출구
      • L : 레버
      • O : 통로
      • X : 벽
    • 시작 지점과 출구, 레버는 항상 다른 곳에 존재하며 한 개씩만 존재합니다.
    • 출구는 레버가 당겨지지 않아도 지나갈 수 있으며, 모든 통로, 출구, 레버, 시작점은 여러 번 지나갈 수 있습니다.

입출력 예
maps result
["SOOOL","XXXXO","OOOOO","OXXXX","OOOOE"] 16
["LOOXS","OOOOX","OOOOO","OOOOO","EOOOO"] -1

입출력 예 설명

입출력 예 #1

주어진 문자열은 다음과 같은 미로이며

image1

다음과 같이 이동하면 가장 빠른 시간에 탈출할 수 있습니다.

image2

4번 이동하여 레버를 당기고 출구까지 이동하면 총 16초의 시간이 걸립니다. 따라서 16을 반환합니다.

입출력 예 #2

주어진 문자열은 다음과 같은 미로입니다.

image3

시작 지점에서 이동할 수 있는 공간이 없어서 탈출할 수 없습니다. 따라서 -1을 반환합니다.

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges



설계 과정

BFS 함수를 생성 -> 인자: start 좌표, arr(maps에 대한 정보 배열), target
1. time = 0 ; const tranX = [-1,1,0,0]; const tranY = [0,0,-1,1];생성
2. 초기 좌표에 값을 방문했다고 하기 위해 X로 바꿈
3. queue에 start 넣기
이제부터 queue가 길이가 0 미만일 때까지 계속 반복
1. queue에 있는 값을 맨앞부터 하나씩 뽑으면서 이 값에 만들어둔 tranX, tranY를 대입함으로써 하나씩 체크
2. 값이 X가 아니고, x,y가 배열 크기를 넘어가지 않으면 queue에 대입하고 그 값을 X로 바꿈.
3. 만약 그 값이 target가 같다면 +1해서 그 값을 리턴
4. 만약 return을 계속 못해서 while문을 빠져나오면 -1을 리턴

  • 위의 함수를 이용해서 아래과정 수행
  1. S, L에 좌표를 찾는다.
  2. 위의 함수에서 쓸 maps 두개 만들기
  3. BFS(S좌표, [...maps], "L"), BFS(L좌표, [...maps], "E") 두개의 함수 실행
  4. 두 값중에 하나라도 -1이라면 -1을 리턴한다.
  5. 둘다 -1이 아니라면 둘을 더해서 리턴


정답 코드

function BFS(start, arr, target){
  var time = 0;
  const tranX  = [-1,1,0,0];
  const tranY = [0,0,-1,1];
  arr[start[0]][start[1]] = "X";
  var queue = [start];

  while(queue.length>0){
    let size = queue.length;
    for(var i = 0;i<size;i++){
      let [x,y] = queue.shift();
      for(var k = 0;k<4;k++){
        let nx = x + tranX[k];
        let ny = y + tranY[k];

        if(nx>=0&&ny>=0&&nx<arr.length&&ny<arr[0].length&&arr[nx][ny]!=="X"){
          if(target === arr[nx][ny]){
            return time+1;
          }

          queue.push([nx,ny]);
          arr[nx][ny] = 'X';
        }
      }
    }
    time++;
  }

  return -1;
}

function solution(maps) {

  var lCord;
  var sCord;
  var maps1 = maps.map((element)=>element.split(""));
  var maps2 = maps.map((element)=>element.split(""));
  for(var x = 0;x<maps.length;x++){
    for(var y = 0;y<maps[0].length;y++){
      if(maps[x][y] === "L"){
          lCord = [x,y];
      }

      if(maps[x][y] === "S"){
        sCord = [x,y];
      }
    }
  }

  var a = BFS(sCord,[...maps1],"L");
  var b = BFS(lCord,[...maps2],"E")

  if(a===-1||b===-1){
    return -1;
  }
 
   return a+b;
}


결과



profile
집돌이 FE개발자의 노트

0개의 댓글