본문 바로가기
일반 학습/코딩 테스트

[프로그래머스] 프렌드 4블록

by StelthPark 2022. 3. 9.

처리조건

풀이

인자로 받은 m은 높이 n은 가로 board는 들어온 블록판이다. board는 ["TTTANT", "RRFACC", "RRRFCC", "TRRRAA", "TTMMMF", "TMMTTJ"] 와 같이 요소가 모두 스트링으로 되어있으니 이를 하나하나 쪼개주자.

 

map을 돌려 각 요소에 split("")를 해준다.

이제부터는 while문을 돌려 깨질 블럭을 검색하고 깨질 블럭을 깨서 0으로 만들고 아래에서부터 0인부분이 있다면 위에서 0이아닌 블럭을 가져와 채우며 다시 깨질 블록을 검색하는 행위를 반복할 것이다. 만약 깨질 블럭이 없다면 블록판 board에 0을 세어 갯수를 리턴하자.

 

각 배열요소에서 자신을 기준으로 오른쪽과 아래 아래대각선에 있는 요소가 자신가 같을시 그 요소의 X,Y좌표를 기억하여 arr배열에 푸시한다.

arr배열이 비어 있다면 깨질 블럭을 더이상 찾을게 없다는 것이며 board 에 있는 0의 갯수를 세어 result에 담아 result의 길이를 리턴한다.

 

이제 깨질 블록의 기준 X,Y가 있으니 X,Y를 기준으로 오른쪽 아래쪽 아래대각선에 각각 0으로 그리고 자신도 0으로 바꾸어준다. 아래와 같이 결과가 나온다.

이제 사이에 있는 0들을 지나 위쪽에 있는 알파벳들이 아래로 내려와야한다. 맨 아래부터 검사하게 될것이며 m이 높이이니 m-1이 가로인덱스 5부터 검색하게 된다. 그리고 if문을 통해 가로 한줄 요소에 0이 포함되어있지않고 모두 알파벳이라면 그냥 다음 for문을 시작하라는 continue를 처리하는데 여기서 some메소드를 잘 알아야 이해할 수 있다.

 

만약 맨 아래 요소인 T M M T T J에 0이 하나도 없으니 그냥 다음for문을 으로 다시 돌아가게되고 또 위에 T T M M M F도 없으니 또 돌아서 올라가게 된다.

 

some메소드는 뭘까? 이건 내부에 콜백함수에서 하나라도 true가 나오면 결과값을 true로 리턴하는 것이다. 그래서 board[i]는 여기서 맨밑 가로한줄부터 되며 가로한줄에 .some을 하여 안에 요소를 v로 하나씩 뽑아 !v로 부정하게된다. 만약 알파벳이라면 !T이므로 false !M도 false이므로 모든 문자가 다 false로 나와 맨 앞 !board[i]에서 !이 있으므로 !false가 되어 true로 리턴된다. 그러면 모든게 알파벳이였고 continue가 작동된다. 만약 0이 하나라도 있었다면 v중 하나가 0 !0은 1이므로 true 결국 true로 나와 board앞 !를 통해 false로되어 0이 하나라도 있으면 continue를 무시하게된다.

 

자. 그다음 for문에서 j는 가로로 한칸움직이는것이다. 우리는 세로로 먼저 한처리를 끝내고 다음 가로로 이동할 것이다.

여기서 j는 n인 가로 길이 만큼 주었다. 다시 내부에서 for문을 돌려 이제 밑에 알파벳과 위쪽에 자신과 누구를 바꿔서 넣을지 처리하는 if문이 있다. 일단 기준인 board[i][j]가 0이여야하고 (바꿀거니까) board[i][k] 는 0이 아니여야한다( board[i][j] 기준 위로 존재하는 board[i][k]) if문에 맞는 board[i][j]와  board[i][k]가 있으면 서로를 바꾸고 board[i][k]에는 0을 채우게 된다. 그림으로 보면 아래와 같다

만약 한번이라도 [i][j]가 [i][k]와 바꾸게 된다면 break로 해당 for문을 나가 다음 왼쪽에 있는 [i][j+1]를 처리해야한다. 그렇지 않으면 위에 있는 서로 바꾸지않은 [i][k]와 또 자신을 바꾸게된다. 예를 들면 위 그림에서 3번째 세로이다. [3,2]인 0이 위의 위 인 F와 바꿀것이고 여기서 break로 안나가게 되면 [3,2]가 F로 바뀐 점에서 다시 맨위 T와 또 바꾸게 되고 순서가 꼬이게 된다.!

 

const solution = (m, n, board) => {
  let answer = 0;
  //1. 먼저 배열의 문자열을 2차원 배열로 나눈다.
  board = board.map((v) => v.split(""));

  //2. 배열에서 지워질 블록의 인덱스를 구해 arr안에 넣는다.
  while (true) {
    const arr = [];
    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][j + 1] &&
          board[i][j] === board[i + 1][j + 1]
        ) {
          arr.push([i, j]);
        }
      }
    }
    // 답을 구하는 로직 : 깨질 블록이 없다면 0인 개수를 세고 리턴한다.
    if (!arr.length) {
    let result=[]
          for(let i=0; i<board.length ;i++){
              for(let j=0; j<board[1].length ; j++)
              if(board[i][j]===0) result.push(board[i][j])
          }
        return result.length
    }

    // 3. 배열에서 지워질 블록을 0으로 바꾼다.
    for (let i = 0; i < arr.length; i++) {
      const col = arr[i][0];
      const row = arr[i][1];
      board[col][row] = 0;
      board[col][row + 1] = 0;
      board[col + 1][row] = 0;
      board[col + 1][row + 1] = 0;
    }

    // 4. 깨진 블록을 없애고 위에서 블록을 당겨온다.
    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 ; k--) { //맨밑줄 바로위
          if (board[i][j]===0 && board[k][j]!==0) {
            board[i][j] = board[k][j];
            board[k][j] = 0;
            break;
          }
        }
      }
    }
  }
};​

'일반 학습 > 코딩 테스트' 카테고리의 다른 글

[프로그래머스] 방금그곡  (0) 2022.03.09
[프로그래머스] 캐시  (0) 2022.03.09
[프로그래머스] 순위 검색  (0) 2022.03.08
[프로그래머스] 튜플  (0) 2022.03.07
[프로그래머스] 수식 최대화  (0) 2022.03.07

댓글