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

nd098pkc·2022년 6월 21일
0

코딩테스트 준비

목록 보기
10/15
post-thumbnail

2021 카카오 채용연계형 인턴십 출제문제이며 레벨2로 구분되어있다.

문제

코로나 사태를 반영한 거리두기 문제이다. 파티션 없이 가로세로 2칸 이내에 있으면 거리두기를 지키지 않은것이며 거리두기를 지키지 않은 방은 0, 지킨방은 1로 표시하여 배열로 출력하면 된다.

풀이과정

<입력>

  1. 각 대기실 별 상황이 나열된 2차원 배열 "places"(Array)

<핵심 아이디어>

조건이 많아보이지만 요약하면 다음과 같다.
1. 대기자(P)의 상하좌우 4칸에 대기자가 1명이라도 있으면 거리두기 실패
2. 빈테이블(O)의 상하좌우 4칸 중 대기자가 2명 이상 있으면 거리두기 실패

그렇다면 우리에게 필요한건 한 칸을 지정해주었을 때 상하좌우에 있는 대기자(P)의 수를 구해주는 함수일것이다.

<상하좌우 탐색>

    function check (idx,cx,cy){ //현재 대기실 = idx번째, 현재칸=[cx][cy]
    const dx = [1,-1,0,0]       //순서대로 상하우좌
    const dy = [0,0,1,-1]        
        let count = 0           // P의 개수를 넣어줄 변수
        for(let i=0;i<4;i++){   
            let nx = cx+dx[i]   // 새로운 x좌표
            let ny = cy+dy[i]   // 새로운 y좌표

            if(nx<0||ny<0||nx>=5||ny>=5) continue;     //배열 범위 벗어나면 무시해주고
            else if(places[idx][nx][ny]==='P') count++ //P일때 카운트++
        }
        return count  
    }

cx,cy 좌표를 넣어주었을때 상하좌우에 P가 몇개 있는지 출력해준다. places의 각 대기실 좌표를 돌다가 P가 나오면 위 함수를 돌려서 해당 칸에서 1이라도 나오면 바로 거리두기 실패로 처리해주고 종료, O가 나오면 해당칸으로 위함수 돌려서 2 이상나왔을때 종료시켜주면 되겠다.

<배열 탐색>

 let answer = []                            //정답 넣어줄 배열, 실패면 0넣고 성공이면 1 넣고
   for(let i=0;i<5;i++){                    //주어질 대기실 수는 항상 5개라고한다.
       let result=1                         //마지막까지 아무일 없으면 1로 남아있을것이다.
   for(let j=0;j<5;j++){                 
       for(let k=0;k<5;k++){                //i번째 대기실의 j행 k열을 탐색해서 
           if(places[i][j][k]==="P"){       //P가 나오면
               if(check(i,j,k)>0){          //check함수 돌려서 0보다 크면(1이라도 나오면)
                   result=0                 //거리두기 실패
                   break;                   //종료
               } 
           }else if(places[i][j][k]==="O"){ //O가 나오면
               if(check(i,j,k)>1){          //check가 2이상일때(P가 2명 이상 있을때)
                   result=0                 //거리두기 실패
                   break;                   //종료
               }     
           }
       }
       if(!result) break;                   //result가 0이면 이미 실패한것이므로 다음줄 가지말고 패스
   }
       answer.push(result)                  //아무일 없었으면 1, 실패했으면 0으로 남아있을 result를 answer에 넣어준다
   }
   return answer                            //모든 대기실을 돌고 나면 정답배열이 완성되어있을것

주어지는 데이터 크기가 작아서 일일이 반복문을 돌리든 어떻게하든 풀수는 있는 문제인것 같은데 효율적인 문제해결을 위한 고민의 결과가 꽤 만족스러웠다.

<전체코드>

function solution(places) {    
    function check (idx,cx,cy){
   	    const dx = [1,-1,0,0]
        const dy = [0,0,1,-1]
        let count = 0
        for(let i=0;i<4;i++){
            let nx = cx+dx[i]
            let ny = cy+dy[i]

            if(nx<0||ny<0||nx>=5||ny>=5) continue;
            else if(places[idx][nx][ny]==='P') count++
        }
        return count
    }
    let answer = []
    for(let i=0;i<places.length;i++){
        let result=1
    for(let j=0;j<5;j++){
        for(let k=0;k<5;k++){
            if(places[i][j][k]==="P"){
                if(check(i,j,k)>0){
                    result=0
                    break;
                } 
            }else if(places[i][j][k]==="O"){
                if(check(i,j,k)>1){
                    result=0
                    break;
                }     
            }
        }
        if(!result) break;
    }
        answer.push(result)
    }
    return answer
    }
profile
늦게배운 코딩이 무섭다

0개의 댓글