[프로그래머스]기둥과 보 설치 (JS)

성도원·2021년 9월 17일
0

프로그래머스

목록 보기
1/3

문제

[2020 KAKAO BLIND RECRUITMENT] 기둥과 보 설치
[링크] https://programmers.co.kr/learn/courses/30/lessons/60061

문제풀이

처음에는 당연히 2차원 배열에 주어진 조건에 맞게 구현해서 해결하려고 했다. 그러기에는 너무 구현이 빡셌다. 그리고 x,y좌표값도 평소에 이용하는 2차원 배열과 맞지 않게 주어졌고, 마지막에 리턴해야하는 정답의 형식도 이해가 되지 않았다.
그렇게 빡구현에 시간을 날리다 다른사람들도 다 이렇게 구현해서 해결하는 것인지 검색해보다가 2차원배열을 선언조차 하지 않는 방법이 있는 것을 보고 충격...
그 풀이방법의 아이디어는 이러하다.

1.빌딩의 현재 상태를 Set으로 만든다.
2.작업 순서에 따라 설치,삭제 한다.
3.설치, 삭제 할때마다 빌딩의 현재 상태가 가능한 상태인지 체크.
4.체크 후 불가능하다면 설치,삭제를 하기이전으로 되돌림.

빌딩의 현재 상태가 가능한지를 체크하는 함수를 만들면 매우 간단하게 해결된다.

  • 기둥 (x,y,0)
  1. 기둥은 바닥에 설치 가능함. y의값이0이면 올바른 기둥 (y===0)
  2. 아래에 기둥이 있으면 올바른 기둥. 현재 빌딩에 (x,y-1,0) 값이 있으면 올바른기둥.
  3. 기둥 시작점 좌,우 중에 보가 있으면 올바른 기둥. 아래에 보가 있는 경우는 (x-1,y,1),(x,y,1) 이다. 마찬가지로 현재 빌딩에 있는지 확인.
  • 보 (x,y,1)
  1. 보는 기둥위에 설치가능. 아래에 기둥이 있는 경우 (x,y-1,0),(x+1,y-1,0) 가 빌딩에 있는지 확인.
  2. 양쪽에 보가 있다면 설치가능. (x-1,y,1)&&(x+1,y,1) 두가지 모두가 빌딩에 있는지 확인.

처음에 조건을 빠짐없이 했는데도 계속 최종 제출에서 3-9번만 맞고 다 틀렸다고 나와서 시간을 많이 썼다.
문제점을 찾다보니 내가 배열을 스트링으로 변환해서 풀었는데,
x=12 y=1,a=0일때 1210이고 x=1,y=21,a=0이어도 1210인 것을 찾아서 사이에 ,를 넣어 해결했다.
'12,1,0' '1,21,0' 이런식으로 수정.

코드

function solution(n, build_frame) {
//빌딩은 add,delete,has를 이용하기 위해 set으로 설정.
   const building = new Set();
   for(let [x,y,a,b] of build_frame){
       if(b===0){
         //빌딩에는 동작(설치,삭제)인 b를 제외하고 x,y,a만 넣어준다. 
         //자바스크립트 set에서는 [1,2]===[1,2]를 false로 반환하기 때문에 set에 스트링으로 만들어 넣어준다.
         //','로 구분해주는 이유는 1<=n<=1000이기 자릿수 구분을 위해서.
           building.delete(x+','+y+','+a);
           if(isPossible(building))continue;//삭제 후에도 가능한 빌딩이면 삭제하고 continue;
           else building.add(x+','+y+','+a);//아닐시 다시 추가해서 삭제를 취소
       }else{
           building.add(x+','+y+','+a);
           if(isPossible(building))continue;//삭제와 동일
           else building.delete(x+','+y+','+a);
       }
   }
 //스트링으로 되어있는 빌딩을 return 조건에 맞추어 다시 숫자배열로 변환함.
   return [...building].map((v)=>v.split(',').map((str)=>Number(str))).sort((a,b)=>{
     //정렬 조건은 x값 우선 이후에 y값,그리고 기둥(0)이 보(1) 보다 우선 결국 모두 오름차순으로 정렬해주면된다.
       if(a[0]===b[0]&&a[1]===b[1]) return a[2]-b[2];
       if(a[0]===b[0])return a[1]-b[1];
       return a[0]-b[0];
   });
 
 //가능한 건물인지 체크하는 함수
 function isPossible(building){
   for(let xya of building){
     //스트링으로 만들어준 xya를 다시 숫자로 변환
       let [x,y,a]=xya.split(',').map(v=>Number(v));
       if(a===0){
         //올바른 기둥 조건
           if(y===0||building.has(x+','+(y-1)+','+0)||building.has((x-1)+','+y+','+1)||building.has(x+','+y+','+1))continue;
           else return false;
       }else{
         //올바른 보 조건
           if(building.has(x+','+(y-1)+','+0)||building.has((x+1)+','+(y-1)+','+0)||(building.has((x-1)+','+y+','+1)&&building.has((x+1)+','+y+','+1)))continue;
           else return false;
       }
   }
   return true;
}

}

0개의 댓글