[프로그래머스] 프렌즈4블록 - javascript

김지원·2022년 2월 12일
0

coding-test

목록 보기
21/25
post-thumbnail

📖 문제링크

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

문제 설명

링크로 들어가면 자세한 설명이 있기때문에 생략하기로 한다.

👨‍💻 문제풀이

필자가 푼 문제풀이

function solution(m, n, board) {
    board = board.map((x) => x.split(""));
    
    while(1) {
        const blocks = [];
        for (let i = 0; i < m - 1; i++) {
            for (let j = 0; j < n - 1; j++) {
                if (board[i][j] && board[i][j] === board[i + 1][j] && board[i][j] === board[i + 1][j + 1] && board[i][j] === board[i][j + 1]) {
                    blocks.push([i, j]);
                }
            }
        }
        
        if (!blocks.length) {
            return [].concat(...board).filter((x) => !x).length;
        }
        
        for (let numbers of blocks) {
            let [i, j] = numbers;
            board[i][j] = 0;
            board[i + 1][j] = 0;
            board[i + 1][j + 1] = 0;
            board[i][j + 1] = 0;
        }
        
        for (let i = m - 1; i > 0; i--) {
            if (!board[i].some((v) => !v)) continue;
            
            for (let j = 0; j < n; j++) {
            const zero = [];
            const text = [];
            
            for (let i = m - 1; i >= 0; i--) {
                !board[i][j] ? zero.push(i) : text.push(i);
            }
            
            if (zero.length !== m) {
                for (let idx in zero) {
                    for (let textIdx in text) {
                        if (zero[idx] > text[textIdx]) {
                            board[zero[idx]][j] = board[text[textIdx]][j];
                            board[text[textIdx]][j] = 0;
                            break;
                            }
                        }
                    }
                }
            }
        }
    }
}
}

필자는 이 문제의 핵심을 터진 후 그 자리를 0으로 치환하고 내리는 작업이라고 생각한다.

일단 주먹구구식으로 2중 for문을 이용해 2*2 블록을 찾았고 찾은 위치를 빈배열에 저장해두었다.

그리고 관련된 위치의 문자들을 모두 0으로 바꿔주었다.

그 다음이 문제였는데..

필자는 if (!board[i].some((v) => !v)) continue; 이부분을 생각하지 못했다.
그래서 테스트 5번 10번이 계속 실패했다.

필자는 블록은 세로로 떨어지니 세로만 신경써서 아래에서부터 0인 부분과 문자의 index를 비교하여 위치를 바꿔주려고 했지만 위의 some을 이용해 가로부분에 문자만 있는지 확인하는 작업이 필요했다.

이번에 some을 이용한 비교방법을 알게 되어 나중에 홀수/짝수나 여러 코테에서 사용할 수 있을 것 같다.

👨‍💻 다른 사람의 코드

function solution(m, n, board) {
    board = board.map(v => v.split(''));

    while (true) {
        let founded = [];

        // 찾기
        for (let i = 1; i < m; i++) {
            for (let j = 1; j < n; j++) {
                if (board[i][j] && board[i][j] === board[i][j - 1] && board[i][j] === board[i - 1][j - 1] && board[i][j] === board[i - 1][j]) {
                    founded.push([i, j]);
                }
            }
        }

        if (! founded.length) return [].concat(...board).filter(v => ! v).length;

        // 부수기
        founded.forEach(a => {
            board[a[0]][a[1]] = 0;
            board[a[0]][a[1] - 1] = 0;
            board[a[0] - 1][a[1] - 1] = 0;
            board[a[0] - 1][a[1]] = 0;
        });

        // 재정렬
        for (let i = m - 1; i > 0; i--) {
            if (! board[i].some(v => ! v)) continue;

            for (let j = 0; j < n; j++) {
                for (let k = i - 1; k >= 0 && ! board[i][j]; k--) {
                    if (board[k][j]) {
                        board[i][j] = board[k][j];
                        board[k][j] = 0;
                        break;
                    }
                }
            }
        }
    }
}

거의 흡사한 코드지만 재정렬 부분이 훨씬 깔끔하다.
가로를 판단하는 for문의 조건문에서 문자만 있는 가로를 제외시켜주어 그런 것으로 보인다.
구현 문제를 더 많이 풀어보고 깔끔한 코드를 만들기 위해 노력해야겠다.

2022.02.12

profile
backend-developer

0개의 댓글