[프로그래머스/JavaScript] 프렌즈4블록

2025. 7. 3. 21:37·Problem Solving/프로그래머스

문제

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

m x n 크기의 게임판이 있다.

같은 그림의 2x2 블록은 지워진다.

블록이 지워진 후에는 위에 있는 블록이 아래로 떨어져 빈 공간을 채우게 된다.

첫 배치가 주어졌을 때, 지워지는 블록이 모두 몇 개인지 계산하려고 한다.

  • 2 ≤ `n`, `m` ≤ 30

풀이

더 이상 지워지는 블록이 없을 때까지 아래의 계산을 반복한다.

  1. 게임판을 순회하면서 같은 그림의 2x2 블록을 찾아서 지워질 모든 블록의 좌표를 계산한다. (`check2x2(map)`)
  2. 지워질 모든 블록을 0으로 변환하며 지워지는 블록을 계산한다. (`replace(map, postitions)`)
  3. 중력이 작용하는 것처럼, 블록을 아래로 떨어뜨린다. (`applyGravity(map)`)

2x2 크기에서 겹치는 좌표가 있을 수 있으므로 중복된 좌표를 제거해야 했다. 블록의 좌표를 `[x, y]` 형태의 배열에 담았었는데, 배열에 담았기에 그대로 Set에 넣어 제거하는 것은 불가능했다. 문자열로 변환한 뒤(`JSON.stringify`), 이것을 다시 파싱하여(`JSON.parse`) 중복을 제거했다.

 

중력을 작용시켜 떨어뜨리는 로직은 2중 반복문으로 작성할 수 있었다. 열을 기준으로 중력을 작용시켜 떨어뜨렸다. 블록이 있다면 `lowestEmptyRow`까지 떨어뜨리게 된다. 0이 아니라면 `lowestEmptyRow`를 감소시켜 한 칸씩 떨어져야 하는 위치를 위로 올리기 때문에, 블록이 떨어져야 하는 가장 아래 칸의 위치를 보장할 수 있다.

 

코드

function solution(m, n, board) {
    const map = board.map(line => line.split(""));
    let removedBlocks = 0;
    
    while (true) {
        // 맵을 순회하면서 2x2를 체크한다.
        const toBeRemoved = check2x2(map, m, n);
        if (toBeRemoved.length === 0) break;
        // 체크된 칸들을 0으로 변환한다.
        const blocks = replace(map, toBeRemoved);
        removedBlocks += blocks;
        // 블록을 아래로 떨어뜨린다.
        applyGravity(map);
    }

    return removedBlocks;
}

function check2x2(map) {
    const arr = [];
    for (let i = 0; i < map.length - 1; i++) {
        for (let j = 0; j < map[0].length - 1; j++) {
            if (map[i][j] === 0) continue;
            if (map[i][j] === map[i][j + 1] 
                && map[i][j + 1] === map[i + 1][j]
                && map[i + 1][j] === map[i + 1][j + 1]) {
                arr.push([i, j]); arr.push([i, j + 1]);
                arr.push([i + 1, j]); arr.push([i + 1, j + 1]);
            }
        }
    }
    return Array.from(new Set((arr.map(e => JSON.stringify(e))))).map(str => JSON.parse(str));
}

function replace(map, positions) {
    let blocks = 0;
    for (const [x, y] of positions) {
        map[x][y] = 0;
        blocks++;
    }
    return blocks;
}

function applyGravity(map) {
    const rows = map.length;
    const cols = map[0].length;
    for (let j = 0; j < cols; j++) {
        let lowestEmptyRow = rows - 1;
        for (let i = lowestEmptyRow; i >= 0; i--) {
            if (map[i][j] !== 0) {
                if (i !== lowestEmptyRow) {
                    map[lowestEmptyRow][j] = map[i][j];
                    map[i][j] = 0;
                }
                lowestEmptyRow--;
            }
        }
    }
}
저작자표시 비영리 동일조건 (새창열림)

'Problem Solving > 프로그래머스' 카테고리의 다른 글

[프로그래머스/JavaScript] 조이스틱  (0) 2025.08.21
[프로그래머스/JavaScript] 소수 찾기  (1) 2025.07.18
[프로그래머스/JavaScript] 파일명 정렬  (0) 2025.07.01
[프로그래머스/JavaScript] 주차 요금 계산  (0) 2025.07.01
[프로그래머스/Java] 다트 게임  (2) 2025.05.30
'Problem Solving/프로그래머스' 카테고리의 다른 글
  • [프로그래머스/JavaScript] 조이스틱
  • [프로그래머스/JavaScript] 소수 찾기
  • [프로그래머스/JavaScript] 파일명 정렬
  • [프로그래머스/JavaScript] 주차 요금 계산
friend5hip
friend5hip
개발 관련 지식이나 기록을 남기고 있습니다.
  • friend5hip
    friend5hip
    friend5hip
  • 전체
    오늘
    어제
    • 분류 전체보기 (60)
      • 컴퓨터공학 (2)
        • 자료구조 (0)
        • 알고리즘 (1)
        • 데이터베이스 (1)
      • Problem Solving (42)
        • BOJ (25)
        • 프로그래머스 (15)
      • 언어 (2)
        • JavaScript (2)
      • 라이브러리 (12)
        • React (12)
      • 개발 (2)
      • 기타 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백트래킹
    매개 변수 탐색
    집합
    백준
    소수 판별
    문자열
    수학
    완전 탐색
    BFS
    그리디
    누적 합
    프로그래머스
    맵
    dfs
    이분 탐색
    vite
    코드트리
    구간 합
    java
    JavaScript
    정렬
    삼성 sw 역량테스트
    투 포인터
    구현
    순열
    dp
    react
    시뮬레이션
    intersection observer
    N과 M
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
friend5hip
[프로그래머스/JavaScript] 프렌즈4블록
상단으로

티스토리툴바