ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스 ] 위클리 챌린지 3주차 - 퍼즐 조각 채우기
    ALGORITHM/PROGRAMMERS 2021. 9. 26. 14:45

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

     

    코딩테스트 연습 - 3주차_퍼즐 조각 채우기

    [[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]] [[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]] 14 [[0,0,0],[1,1,0],[1,1,1]] [[1,1,1],[1,0,0],[0,0,0]] 0

    programmers.co.kr

    2021-09-26


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    import java.util.*;
     
    class Solution {
        public static ArrayList<int[][]> game, tab; // game_board 와 tab을 조각별로 저장 
        public static int[] dx = {-1010};
        public static int[] dy = {0-101};
        // extract blocks -> game, tab
        public static void extract(int[][] arr, int flag, int x, int y, boolean[][] vtd) { // flag == 0 : game, flag == 1 : tab
            Queue<int[]> q = new LinkedList<>();
            q.add(new int[]{x, y});
            vtd[x][y] = true;
            ArrayList<int[]> list = new ArrayList<>();
            list.add(new int[]{x,y});
            // 블록 추출하기
            while(!q.isEmpty()) {
                int[] tmp = q.poll();
                int cx = tmp[0];
                int cy = tmp[1];
     
                for(int i = 0; i < dx.length; i++) {
                    int nx = cx + dx[i];
                    int ny = cy + dy[i];
     
                    if (nx < 0 || ny < 0 || nx >= arr.length || ny >= arr.length || vtd[nx][ny] || arr[nx][ny] != flag)
                        continue;
                    else {
                        vtd[nx][ny] = true;
                        q.add(new int[]{nx, ny});
                        list.add(new int[]{nx, ny});
                    }
                }
            }
            
            int xmin = 987654321;
            int xmax = -987654321;
            int ymin = 987654321;
            int ymax = -987654321;
            // 추출한 블록 기준, x, y 각각 min, max 값 구하기 
            for(int i = 0; i < list.size(); i++) {
                xmin = Math.min(list.get(i)[0], xmin);
                xmax = Math.max(list.get(i)[0], xmax);
                ymin = Math.min(list.get(i)[1], ymin);
                ymax = Math.max(list.get(i)[1], ymax);
            }
     
            int[][] temp = new int[xmax-xmin+1][ymax-ymin+1];
            // 2차원 배열에 추출한 븝록 넣기 
            for (int[] ints : list) {
                ints[0-= xmin;
                ints[1-= ymin;
                temp[ints[0]][ints[1]] = 1;
            }
            // flag == 0 -> game, flag == 1 -> tab
            if(flag == 0) Collections.addAll(game, temp);
            else Collections.addAll(tab, temp);
        }
     
        // rotate
        public static boolean rotate(int game_idx, int table_idx) {
            // 배열을 돌리기 전에 같으면 바로 true 넘기기
            if(Arrays.deepEquals(game.get(game_idx), tab.get(table_idx))) return true;
     
            //rotate 90도 시계방향으로 3번 진행
            int[][] tmp = tab.get(table_idx);
     
            for(int pp = 0; pp < 3; pp++) {
                int[][] rot = new int[tmp[0].length][tmp.length];
                for(int i = 0; i < tmp.length; i++) {
                    for(int j = 0; j < tmp[i].length; j++) {
                        // ex. tmp (0, 1) -> rot (1, rot[j].length - i - 1) 
                        // x, y 값 위치 바꾸고 새로운 y값은 계산
                        rot[j][rot[j].length - i - 1=  tmp[i][j];
                    }
                }
                // 맞으면 바로 true 아니면 회전에서 계속 체크 
                if(Arrays.deepEquals(game.get(game_idx), rot)) return true;
                tmp = rot;
            }
            return false;
        }
        // match 체크 
        public static int match(int game_idx, int table_idx, boolean[] used) {
            int count = 0;
            // false면 매치 불가
            if(!rotate(game_idx, table_idx)) return 0;
            // match 가능하면, 블록 칸 수 세기 
            int[][] temp = game.get(game_idx);
            for(int i = 0; i < temp.length; i++) {
                for(int j = 0; j < temp[i].length; j++) {
                    if(temp[i][j] == 1) count++;
                }
            }
            // 사용한 부분 체크
            used[table_idx] = true;
            return count;
        }
     
        public static int solution(int[][] game_board, int[][] table) {
            int answer = 0;
            game = new ArrayList<>();
            tab = new ArrayList<>();
            // game_board 블록 추출
            boolean[][] vtd = new boolean[game_board.length][game_board[0].length];
            for(int i = 0; i < game_board.length; i++) {
                for(int j = 0; j < game_board[i].length; j++) {
                    if(!vtd[i][j] && game_board[i][j] == 0) {
                        extract(game_board, 0, i, j, vtd);
                    }
                }
            }
            
            // table 블록 추출
            vtd = new boolean[table.length][table[0].length];
            for(int i = 0; i < table.length; i++) {
                for(int j = 0; j < table.length; j++) {
                    if(!vtd[i][j] && table[i][j] == 1) {
                        extract(table, 1, i, j, vtd);
                    }
                }
            }
     
            //game, tab 매치 체크 
            boolean[] used = new boolean[tab.size()];
            for(int i = 0; i < game.size(); i++) {
                for(int j = 0; j < tab.size(); j++) {
                    if(!used[j]) {
                        int ans = match(i, j, used);
                        answer += ans;
                        if(ans > 0break;
                    }
                }
            }
     
            return answer;
        }
    }
    cs

    #문제풀이 

    1) game_board에서 블록을 추출한다.

    2) table에서 블록을 추출한다.

    3) gmae_board와 table에서 각각 추출한 블록들을 table을 회전하면서 서로 매칭이 되는지 체크한다. 

     

    댓글

Programming Diary