개발 공부/알고리즘 문제 풀이

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

종범2 2020. 6. 1. 09:22

문제

프로그래머스 2020 KAKAO BLIND RECRUITMENT 기둥과 보 설치

 

언어

자바스크립트(JavaScript)

 

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

 

코딩테스트 연습 - 기둥과 보 설치

5 [[1,0,0,1],[1,1,1,1],[2,1,0,1],[2,2,1,1],[5,0,0,1],[5,1,0,1],[4,2,1,1],[3,2,1,1]] [[1,0,0],[1,1,1],[2,1,0],[2,2,1],[3,2,1],[4,2,1],[5,0,0],[5,1,0]] 5 [[0,0,0,1],[2,0,0,1],[4,0,0,1],[0,1,1,1],[1,1,1,1],[2,1,1,1],[3,1,1,1],[2,0,0,0],[1,1,1,0],[2,2,0,1]] [[

programmers.co.kr

 

접근 방법

  1. 모든 build_frame의 요소에 대해 실행할 행동이 기둥 설치, 보 설치, 기둥 삭제, 보 삭제 인지를 구분한다.
  2. 가능한 행동인지 체크하고 행동을 실행한다.
    1. 기둥 설치의 경우 바닥이거나, 밑에 기둥이 있거나, 현재 위치를 기준으로 보가 있거나, 왼쪽 위치를 기준으로 보가 있으면 설치가 가능하다.
    2. 보 설치의 경우 밑에 기둥이 있거나, 오른쪽 밑에 기둥이 있거나, 양 옆에 보가 있으면 설치가 가능하다.
    3. 기둥이나 보의 삭제의 경우 해당 요소를 삭제한다. 이후 모든 요소에 대해서 기둥은 2-1의 조건을 만족하고 보는 2-2의 조건을 만족하면 삭제한다.
  3. 실행한 행동을 조건에 맞게 정렬한다.

코드

function solution(n, build_frame) {
    var currentFrame = [];
    for (let i=0; i<build_frame.length; i++){
        if (build_frame[i][2] == 0 && build_frame[i][3] == 0){
            // 기둥 삭제
            destroyColumn(currentFrame, build_frame[i][0], build_frame[i][1]);
        }else if (build_frame[i][2] == 0 && build_frame[i][3] == 1){
            // 기둥 설치
            buildColumn(currentFrame, build_frame[i][0], build_frame[i][1]);
        } else if (build_frame[i][2] == 1 && build_frame[i][3] == 0){
            // 보 삭제
            destoryFloor(currentFrame, build_frame[i][0], build_frame[i][1]);
        } else if (build_frame[i][2] == 1 && build_frame[i][3] == 1){
            // 보 설치
            buildFloor(currentFrame, build_frame[i][0], build_frame[i][1]);
        }
    }
    currentFrame.sort((a,b)=>{
        if (a[0]>b[0]){
            return 1;
        }else if (a[0]<b[0]){
            return -1;
        }else {
            if (a[1]>b[1]){
                return 1;
            }else if (a[1]<b[1]){
                return -1;
            }else{
                if (a[2]>b[2]){
                    return 1;
                }else if (a[2]<b[2]){
                    return -1;
                }
            }
        }
    })
    console.log(currentFrame);
    return currentFrame;
}
function checkColumn(currentFrame, x, y){
    let result = false;
    // 바닥이면 항상 기둥 설치 가능
    if (y ===0){
        result = true;
    // 밑에 기둥이 있으면 설치 가능
    }else if (currentFrame.find(ele => (ele[0]===x && ele[1]===(y-1) && ele[2] ===0)) !== undefined){
        result = true;
    // 왼쪽에 보가 있으면 설치 가능
    }else if (currentFrame.find(ele => (ele[0]===x-1 && ele[1]===y && ele[2] ===1)) !== undefined){
        result = true;
    // 그 위치에 보가 있으면 설치 가능
    }else if(currentFrame.find(ele => (ele[0]===x && ele[1]===y && ele[2] ===1)) !== undefined){
        result = true;
    }
    return result;
}
function buildColumn(currentFrame, x, y){
    if (checkColumn(currentFrame, x, y)){
        currentFrame.push([x,y,0]);
        console.log(`${x}, ${y} 기둥 설치`);
    }else{
        console.log(`${x}, ${y} 기둥 설치 실패`);   
    }
    return currentFrame;
}
function checkFloor(currentFrame, x, y){
    let result = false;
     // 밑에 기둥이 있으면 설치 가능
    if (currentFrame.find(ele => (ele[0]===x && ele[1]===(y-1) && ele[2] ===0)) !== undefined){
        result = true;
    // 오른쪽 밑에 기둥이 있을때 설치 가능
    }else if(currentFrame.find(ele => (ele[0]===(x+1) && ele[1]===(y-1) && ele[2] ===0)) !== undefined){
        result = true;
    // 왼쪽과 오른쪽에 보가 위치할 때 설치 가능
    }else if ((currentFrame.find(ele => (ele[0]===x-1 && ele[1]===y && ele[2] ===1)) !== undefined)
    &&(currentFrame.find(ele => (ele[0]===(x+1) && ele[1]===y && ele[2] ===1)) !== undefined)){
        result = true;
    }
    return result;
}
function buildFloor(currentFrame, x, y){
    if (checkFloor(currentFrame, x, y)){
        currentFrame.push([x,y,1]);
        console.log(`${x}, ${y} 보 설치`);
    }else{
        console.log(`${x}, ${y} 보 설치 실패`);   
    }
    return currentFrame;
}
function destroyColumn(currentFrame, x, y){
    // 현재 위치의 기둥 임시 삭제
    let tempFrame = Object.assign([], currentFrame);
    let findItem = tempFrame.find(ele => (ele[0]===x && ele[1]===y && ele[2] ===0));
    let idx = tempFrame.indexOf(findItem);
    tempFrame.splice(idx,1);
    // 모든 기둥과 보의 조건을 체크
    let result = true;
    for (let i=0; i<tempFrame.length; i++){
        if (tempFrame[i][2]==0){
            if(!checkColumn(tempFrame, tempFrame[i][0], tempFrame[i][1]))
                result = false;                              
        }else {
            if(!checkFloor(tempFrame,tempFrame[i][0], tempFrame[i][1]))
                result = false;
        }
    }
    if (result){
        console.log(`${x}, ${y} 기둥 삭제`);    
        currentFrame.splice(idx,1);
    }else{
        console.log(`${x}, ${y} 기둥 삭제 실패`);
    }
    
}
function destoryFloor(currentFrame, x, y){
    // 현재 위치의 기둥 임시 삭제
    let tempFrame = Object.assign([], currentFrame);
    let findItem = tempFrame.find(ele => (ele[0]===x && ele[1]===y && ele[2] ===1));
    let idx = tempFrame.indexOf(findItem);
    tempFrame.splice(idx,1);
    // 모든 기둥과 보의 조건을 체크
    let result = true;
    for (let i=0; i<tempFrame.length; i++){
        if (tempFrame[i][2]===0){
            if(!checkColumn(tempFrame, tempFrame[i][0], tempFrame[i][1]))
                result = false;                              
        }else {
            if(!checkFloor(tempFrame,tempFrame[i][0], tempFrame[i][1]))
                result = false;
        }
    }
    if (result){
        console.log(`${x}, ${y} 보 삭제`);    
        currentFrame.splice(idx,1);
    }else{
        console.log(`${x}, ${y} 보 삭제 실패`);
    }
}

 

 

복기

  1. 처음에 조건을 완벽하게 이해하지 않고 코드를 작성해 시간을 많이 썼다.
  2. 다 풀고 보니 쉬운 문제 같은데 풀 때는 너무 어려웠다.
  3. 기둥을 삭제하거나 보를 삭제할 때에 기둥을 설치할 때 사용한 함수와 보를 설치할 때 사용한 함수를 활용하면 실수도 줄이고 시간도 덜 사용했을 것이다. 이를 인지하지 못하고 삭제 조건을 따지는 함수를 작성했었다. 이 함수는 복잡해서 작성이 오래 걸렸고 조건을 놓쳐 문제를 풀지도 못했다.
  4. 처음부터 기둥 설치 함수, 보 설치 함수, 삭제 시 모든 요소를 설치할 때 작성한 함수를 이용해서 체크하고 만족하면 삭제하도록 코드를 짰으면 더 쉽고 빠르게 풀었을 듯하다.