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

[프로그래머스] [1차] 프렌즈4블록

종범2 2020. 6. 9. 21:52

문제

프로그래머스 2018 KAKAO BLIND RECRUITMENT [1차] 프렌즈4블록

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

 

코딩테스트 연습 - [1차] 프렌즈4블록

프렌즈4블록 블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 프렌즈4블록. 같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙��

programmers.co.kr

언어

자바스크립트(JavaScript)

 

접근 방법

  1. board를 2차원 배열로 변환한다.
  2. 2차원 배열로 변환한 배열 myBoard와 이 배열을 복사한 newBoard를 생성한다.
  3. myBoard를 기준으로 x=i, y=j 좌표가 삭제 가능한지 모두 확인한다. 삭제 확인은 (x,y), (x+1,y), (x,y+1), (x+1,y+1) 기준으로 하고 가능하면 삭제한다. 삭제 표시는 newBoard에 *로 바꿔가면서 한다.
  4. newBoard를 기준으로 삭제된 부분을 채워준다. x=i인 newBoard에서 *를 삭제하고 모운 다음 부족한 수만큼 앞에서 *를 다시 삽입하여 재배열한다.
  5. 2부터 4 과정까지 삭제할 요소가 없으면 그만하고 있다면 다시 삭제를 시작한다.

코드

function solution(m, n, board) {
    // 문자열 배열로 변환
    let myBoard = [];
    for (let i=0; i<m; i++){
        myBoard.push(board[i].split(''));
    }
    // myBoard를 기준으로 삭제 가능한 부분 모두 알아낸 후에 복사한 newBoard 삭제 표시
    // 그후 다시 myBoard에 newBoard를 복사
    let newBoard = JSON.parse(JSON.stringify( myBoard ))
    while(true){
        let isErase = false;
        //삭제
        for (let i=0; i<n-1; i++){
            for (let j=0; j<m-1; j++){
                // x=i, y=j 좌표 삭제 가능한지 확인
                // 삭제확인은 (x,y), (x+1,y), (x,y+1), (x+1,y+1) 기준으로하고 가능하면 삭제
                if(erase(i, j, myBoard, newBoard))
                    isErase = true;
            }
        }
        // 삭제된 부분 채워주며 다시 배열
        for (let i=0; i<n; i++){
            // x=i,라인 재배열
            // '*' 다 빼서 맨 밑으로 배치
            arrange(m, i, newBoard);    
        }
        myBoard = JSON.parse(JSON.stringify( newBoard ))
        // 더 이상 삭제할 수 중지
        if(!isErase)
            break;
    }
    let cnt =0;
    for (let i=0; i<n; i++){
        for (let j=0; j<m; j++){
            if (newBoard[j][i] === '*')
                cnt++;
        }
    }
    console.log(newBoard);
    return cnt;
}
function arrange(ylen, x, newBoard){
    // 세로줄에 *를 모두 삭제하고 모운다음 부족한 수만큼 앞에서 삽입
    let strList = [];
    for (let i=0; i<newBoard.length; i++){
        strList.push(newBoard[i][x]);
    }
    strList = strList.filter(ele=> ele!=='*');
    let erasedLen = strList.length;
    for (let i=0;i<ylen-erasedLen; i++){
        strList.unshift('*');
    }
    for (let i=0; i<ylen; i++){
        newBoard[i][x] = strList[i];
    }
}
function erase(x,y,board,newBoard){
    // board를 기준으로 삭제 가능하면 가능한 영역 newBoard에 표시
    let isErase = false;
    let xy = board[y][x];
    let x1y = board[y][x+1];
    let xy1 = board[y+1][x];
    let x1y1 = board[y+1][x+1];
    if (xy === '*')
        return isErase;
    if(xy===x1y && x1y===xy1 && xy1===x1y1){
        newBoard[y][x] = '*';
        newBoard[y][x+1] = '*';
        newBoard[y+1][x] = '*';
        newBoard[y+1][x+1] = '*';
        isErase = true;
    }
    return isErase;
}

복기

  1. 삭제할 때 filter를 써서 다 삭제하고 다시 넣는 방법이 계산 상으로 가장 효율적인 방법인 지 모르겠다. 코드 작성하기에 쉽고 가독성이 높도록 작성했다.
  2. 작성해야 하는 코드 양이 많은 문제라 네이밍과 주석에 신경을 많이 쓰지 않으면 헷갈렸다. 좀 더 차분하게 신경 써서 풀어야겠다.