프로그래머스 L2 - 거리두기 확인하기

이종호·2021년 7월 26일
0

알고리즘

목록 보기
9/10

문제

https://programmers.co.kr/learn/courses/30/lessons/81302

해결

function solution(places) {
  var answer = [];
  let isDone = false; // 반복을 덜 하기 위한 flag 변수
  
  // 거리두기가 위반될 경우의 좌표 종류
  let directArr = [[0, 2], [1, 1], [2, 0], [1, -1], [0, -2], [-1, -1], [-2, 0], [-1, 1], [1, 0], [0, 1], [-1, 0], [0, -1]];

  places.forEach(place => {
    place = place.map(v => v.split(''));
    
    for(let i = 0; i < 5; i++ ){
      for(let j = 0; j < 5; j++) {
        if(place[i][j] === 'P') {
          // 거리부터 확인
          let i2, j2;
          for(let k = 0; k < directArr.length; k++) {
            i2 = directArr[k][0] + i;
            j2 = directArr[k][1] + j;

            if(i2 < 0 || i2 > 4 || j2 < 0 || j2 > 4){
              continue;
            }
  
            if(place[i2][j2] === 'P') {
              let dx = i > i2 ? i - i2 : i2 - i
              let dy = j > j2 ? j - j2 : j2 - j
              let d = dx + dy;
  
              if(d === 1) { // 1. 바로 인접한 경우
                isDone = true; 
                break;
              } else if(dx === 2 || dy === 2) { // 2. 직선으로 위반한 경우
                if((dx === 2 && place[Math.min(i, i2) + 1][j] !== 'X') || (dy === 2 && place[i][Math.min(j, j2) + 1] !== 'X')) {
                  isDone = true;
                  break;
                } 
              } else { // 3. 대각으로 위반한 경우
                if(!((place[i][j2] === 'X') && (place[i2][j] === 'X'))){
                  isDone = true;
                  break;
                }
              }
            }
          }
          if(isDone) break;
        }
      }
      if(isDone) break;
    }

    if(isDone) answer.push(0)
    else answer.push(1);

    isDone = false;
  })
  return answer;
}


/** 
  let places = [
    ["POOOP", "OXXOX", "OPXPX", "OOXOX", "POXXP"], 
    ["POOPX", "OXPXP", "PXXXO", "OXXXO", "OOOPP"], 
    ["PXOPX", "OXOXP", "OXPOX", "OXXOP", "PXPOX"], 
    ["OOOXX", "XOOOX", "OOOXX", "OXOOX", "OOOOO"], 
    ["PXPXP", "XPXPX", "PXPXP", "XPXPX", "PXPXP"]
  ];
  let result = [1, 0, 1, 1, 1];
  console.log('my Answer: ',solution(places));
  console.log('Real Answer: ', result);
*/

풀이

  • isDone: 반복문을 빠져나오기 위한 flag이자, 위반할 경우를 확인할 수 잇는 flag입니다.
  • directArr: 먼저 거리두기를 위반한 좌표에 사람이 있는지 확인하기 위해 하나의 P를 중심으로 위반할 수 있는 모든 경우의 좌표를 담은 배열을 준비했습니다.
  • places를 반복하고, 접근하기 쉽게 place를 split를 통해 배열에 하나씩 넣습니다.
  • 방의 크기는 항상 5*5로 일정하니 상수로 넣습니다.
  • directArr에 해당하는 좌표값을 얻어 확인합니다.
 if(i2 < 0 || i2 > 4 || j2 < 0 || j2 > 4){
  continue;
}

if문을 통해 좌표평면을 벗어난 경우를 벗어납니다.

  • if(place[i2][j2] === 'P')이라면 3가지 경우가 있습니다.
  • 1. 거리가 1인 경우 => 바로 인접하게 사람이 있는 경우 입니다.
    |
    이는 다른 조건을 검사할 필요없이 위반한 경우 이므로 바로 isDone을 true하고 반복문을 빠져나옵니다.
  • 2. 하나의 거리가 2인 경우 => 직선상에 P가 있는 경우
    |
    이는 해당 직선 사이에 X가 있는지 확인합니다.
  • 3. 그 외는 대각에 있는 경우만 있습니다.
    |
    이럴 경우엔, 해당 좌표 사이에 모두 X가 있는지 확인해 줍니다.

느낀점

  • 설명이 길지만 차근차근 접근하면 풀 수 있다고 생각합니다.

  • 역시나 시간은 오래 걸렸지만, 그래도 혼자 풀었다는 것에 큰 의의를 두고 있습니다.

  • 생각보다 문제푸는게 너무 즐거웠습니다.

  • 뭔가 역시 L2는 풀만하긴 하지만, 잘못하면 코드가 산으로 가버리는 경우가 많은 것 같습니다. 생각을 잘 정리해서 구현하는 능력이 많이 요구되는 것 같습니다.

  • 이번에 처음으로 vsCode에 debug기능을 활용해봤는데 엄청신기하고 편리한 것 같습니다.

  • 아직은 많은 기능을 사용하진 못하지만 다시 엘리님 강의를 보면서 차근차근 써보려 합니다.

    https://www.youtube.com/watch?v=IwC-BVM2_YQ

profile
코딩은 해봐야 아는 것

0개의 댓글