< 문제 바로가기 >
/**
* 2차원 배열을 받아서 오른쪽으로 90도 회전하는 함수
*
* @param {number} row 행의 개수
* @param {number} col 열의 개수
* @param {(string | boolean)[][]} matrix 2차원 배열
* @returns {(string | boolean)[][]} 오른쪽으로 90도 회전한 2차원 배열
*/
function rotate(row, col, matrix) {
let result = [];
for (let j = 0; j < col; j += 1) {
let tmp = [];
for (let i = 0; i < row; i += 1) {
tmp.push(matrix[i][j]);
}
result.push(tmp.reverse());
}
return result;
}
/**
* 현재 board를 받아서 지워질 개수를 반환하는 함수
*
* @param {number} row 행의 개수
* @param {string[][]} board 게임 판
* @param {boolean[][]} isBlock 2*2 블록이면 true값을 가지는 2차원 배열
* @returns {number} 지워지는 개수
*/
function check(row, board, isBlock) {
let result = 0;
const DIR = {
RIGHT: [0, 1],
DOWN: [1, 0],
RIGHT_DOWN: [1, 1],
};
let flag = true; // 2*2 블록이 완성될 수 있는지 판단하는 flag
for (let i = 0; i < row - 1; i += 1) {
for (let j = 0; j < board[i].length - 1; j += 1) {
flag = true;
const CUR = board[i][j];
for (const [ROW, COL] of Object.values(DIR)) {
const [NEXT_ROW, NEXT_COL] = [i + ROW, j + COL];
// 2*2 블록이 완성되지 못할 경우 break
if (board[NEXT_ROW][NEXT_COL] !== CUR) {
flag = false;
break;
}
}
// 2*2 블록이 완성될 경우
if (flag) {
// 현재 인덱스의 값을 true로 바꾸고
isBlock[i][j] = true;
// 오른쪽, 아래, 오른쪽아래의 값도 true로 바꿔줌
for (const [ROW, COL] of Object.values(DIR)) {
const [NEXT_ROW, NEXT_COL] = [i + ROW, j + COL];
// 중복되어 이미 바뀐 값이라면 continue
if (isBlock[NEXT_ROW][NEXT_COL] === true) continue;
isBlock[NEXT_ROW][NEXT_COL] = true;
}
}
}
}
// true의 값을 세서 answer에 더해줌
for (let i = 0; i < row; i += 1) {
for (let j = 0; j < isBlock[i].length; j += 1) {
if (isBlock[i][j] === true) result += 1;
}
}
return result;
}
/**
* 2*2 블록을 지우는 함수
*
* @param {number} row 행의 개수
* @param {string[][]} board 게임 판
* @param {boolean[][]} isBlock 2*2 블록이면 true값을 가지는 2차원 배열
*/
function deleteBlock(row, board, isBlock) {
// true값이 아닌, 즉 2*2 블록이 완성되지 않은것만 filter로 걸러줌
for (let i = 0; i < row; i += 1) {
board[i] = board[i].filter((_, j) => {
return isBlock[i][j] === false;
});
isBlock[i] = isBlock[i].filter((el) => el === false);
}
}
function solution(m, n, board) {
let answer = 0;
let [row, col] = [m, n];
let isBlock = Array.from({ length: row }, () => new Array(col).fill(false));
// 오른쪽으로 90도 회전
board = rotate(row, col, board);
isBlock = rotate(row, col, isBlock);
// 90도 회전으로 인해 행과 열이 서로 바뀜
[row, col] = [n, m];
let deletedCount = check(row, board, isBlock);
// 지워지는 개수가 0이 될때까지, 즉 지워지는 것이 없을때까지 반복
while (deletedCount) {
answer += deletedCount;
deleteBlock(row, board, isBlock);
deletedCount = check(row, board, isBlock);
}
return answer;
}
2021.10.14 - [PS/Programmers] - Programmers / Level1 / 크레인 인형뽑기 / C++ / JS
예전에 풀어봤던 크레인 인형뽑기 문제가 2차원 배열을 사용하고 같은것을 지운다는 공통점에서 이 문제가 생각이났다.
그래서 일단 똑같이 board를 오른쪽으로 90도를 돌린 뒤 진행하였다.
오른쪽으로 90도를 돌려서 풀이를 진행했을때의 장점은, 열이 행으로 바뀐다는 것이다.
2*2의 블록을 지웠을때 지운 블록 위에 있는것들이 밑의 행으로 내려와야 하는데,
그냥 구현하기엔 어려우므로 열에서의 계산을 행에서의 계산으로 바꾸면 간단히 slice나 배열 method로 간단히 할 수 있기 때문이다.
이것만 잘해주면 더이상 지울것이 없을때까지 계속 지워주면서 카운팅해주면 된다.
'PS > Programmers' 카테고리의 다른 글
Programmers / Level 2 / 게임 맵 최단거리 / JS (0) | 2022.12.10 |
---|---|
Programmers / Level 2 / [1차] 뉴스 클러스터링 / JS (0) | 2022.12.10 |
Programmers / Level 1 / 옹알이 (2) / JS (0) | 2022.11.25 |
Programmers / Level 0 / 저주의 숫자 3 / JS (0) | 2022.10.26 |