컴퓨터과학/기술 면접 대비

[프로그래머스 / JAVA] [1차] 프렌즈4블록 (정답 코드 / not good)

미스터박 2025. 4. 11. 18:03

막히거나 틀린 부분이 있더라도, 그냥 그대로 내가 스스로 작성한 부분들을 기록하고 있다.
미래의 복기용으로 나를 위해 적어둔 기록이다.
(이 사람은 어떻게 실패하거나 성공했는지 살펴보는 용도로도 적합할 것 같다.)


너무 오랫동안 푼 문제라서 기록으로 남겨본다.

처음에는 이 게임판을 그냥 char[][] 형식으로 설정했는데, 만들다 보니까 각 열을 (수직) 하나의 ArrayList로 두고 맨 아래를 index 0으로 설정하고 만들면 remove()를 통해서 그냥 빈칸이 메꿔질 수 있겠다는 생각이 들었다.

 

ArrayList 중간의 요소를 삭제하면 뒤에서부터 앞으로 당겨지는데, 마찬가지로 블록들도 위에서 아래로 쌓이기 때문이다.

 

근데 일단 구현 중간에 이 아이디어가 떠올라서, 일단은 배열을 빡구현하는 방식으로 풀어보았다.

다음 글에서 ArrayList를 활용한 풀이를 올려볼 생각이다.

 

이렇게 푸니, 만들어야 할 메서드도 너무 많고 시간도 너무 오래걸렸다.

그리고 중간에 오류도 너무 많아져서, 디버깅에 시간이 너무 오래 걸렸다.

자잘한 버그들을 피하려면 최대한 제공하는 자료구조나 라이브러리의 이점을 활용하자.

 

import java.util.*;

class Solution {
    private static char[][] Board;
    private static boolean[][] EraseMap; // 선택되어 지워져야할 블록 체크
    private static int M, N;
    private static int Cnt = 0;
    public int solution(int m, int n, String[] board) {
        M = m;
        N = n;
        Board = new char[M][N];
        
        // Board 채우기
        for(int i = 0; i < M; i++) {
            char[] row = board[i].toCharArray();
            for (int j = 0; j < N; j++) {
                Board[i][j] = row[j];
            }
        }
        
        // 2x2 안찾아질때까지 반복
        
        
        while(true) {
            EraseMap = new boolean[M][N];
            boolean found = false; 
            for (int i = 0; i < M-1; i++) {
                for (int j = 0; j < N-1; j++) {
                    if(isSameTwoTwo(i, j)) { // 2x2 발견
                        deleteTwoTwo(i, j);
                        found = true;
                    }
                }
            }
            if(found == false) // 2x2발견 못하면 종료
                break;
            else { // 2x2 발견 다 하면 이제 ' ' 로 표시된 부분 위에서 아래로 빈칸 다 매꿔주기
                fillBlanks();
                found = false; // 내린 다음 또 발견을 위해 false으로 초기화
            }
        }
        
        // System.out.println(Arrays.deepToString(Board));
        return Cnt;
    }
    
    private static boolean isSameTwoTwo(int r, int c) {
        char leftTop = Board[r][c];
        if (leftTop == ' ')
            return false;
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                if (!isInside(r, c) || Board[r + i][c + j] != leftTop) {
                    return false;
                }
            }
        }
        return true;
    }
    
    private static void deleteTwoTwo(int r, int c) { // Erase 맵에 지워야할 블록 체크
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                if(EraseMap[r + i][c + j] == false) {
                    EraseMap[r + i][c + j] = true;
                    Cnt++;
                }
            }
        }
    }
    
    private static void fillBlanks() {
        // 먼저 EraseMap 참고해서 빈칸으로 다 바꿔주기
        // System.out.println("before");
        // printBoard(Board);
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if(EraseMap[i][j] == true) {
                    Board[i][j] = ' ';
                    EraseMap[i][j] = false;
                }
            }
        }
        // System.out.println("middle");
        // printBoard(Board);
        // 왼쪽 열부터 오른쪽으로 훑기
        for (int c = 0; c < N; c++) {
            // 아래 행부터 위로 훑기 (빈칸 찾기)
            int lowestBlankRow = -1; // 빈칸중 맨 아래
            for (int r = M - 1; r >= 0; r--) {
                if (lowestBlankRow == -1 && Board[r][c] == ' ') { // 제일 아래 빈칸 찾았으면
                    lowestBlankRow = r;
                } else if (lowestBlankRow != -1 && Board[r][c] != ' ') { // 아래 빈칸이 있는데 채워져있는 블록을 찾음
                    char block = Board[r][c];
                    Board[lowestBlankRow][c] = block; // 아래의 빈칸 위에서 내려서 채우기
                    Board[r][c] = ' '; // 아래로 내렸으니 빈칸으로 만들기
                    r = lowestBlankRow;
                    lowestBlankRow = -1; // 다시 탐색을 위해 초기화
                }
            }
        }
        
        // System.out.println("after");
        // printBoard(Board);
    }
    
    private static boolean isInside(int r, int c) {
        return (0 <= r && r < M && 0 <= c && c < N);
    }
    
    private static void printBoard(char[][] board) {
        for(char[] row : board) {
            System.out.println(Arrays.toString(row));
        }
    }
}

 


하루에 한 문제 이상 꾸준히 풀자.

실수는 많이 할수록, 더 많이 배울 수 있다.

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

 

프로그래머스

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

programmers.co.kr