[프로그래머스] 레벨2 (level2) 프렌즈4블록

2020년 05월 25일, 10:20

블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 프렌즈4블록. 같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.

pang1

만약 판이 위와 같이 주어질 경우, 라이언이 2×2로 배치된 7개 블록과 콘이 2×2로 배치된 4개 블록이 지워진다. 같은 블록은 여러 2×2에 포함될 수 있으며, 지워지는 조건에 만족하는 > 2×2 모양이 여러 개 있다면 한꺼번에 지워진다.

pang2

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

pang3

만약 빈 공간을 채운 후에 다시 2×2 형태로 같은 모양의 블록이 모이면 다시 지워지고 떨어지고를 반복하게 된다.

pang4

위 초기 배치를 문자로 표시하면 아래와 같다.

TTTANT
RRFACC
RRRFCC
TRRRAA
TTMMMF
TMMTTJ

각 문자는 라이언(R), 무지(M), 어피치(A), 프로도(F), 네오(N), 튜브(T), 제이지(J), 콘(C)을 의미한다

입력으로 블록의 첫 배치가 주어졌을 때, 지워지는 블록은 모두 몇 개인지 판단하는 프로그램을 제작하라.

입력 형식

  • 입력으로 판의 높이 m, 폭 n과 판의 배치 정보 board가 들어온다.
  • 2 ≦ n, m ≦ 30
  • board는 길이 n인 문자열 m개의 배열로 주어진다. 블록을 나타내는 문자는 대문자 A에서 Z가 사용된다.

출력 형식 입력으로 주어진 판 정보를 가지고 몇 개의 블록이 지워질지 출력하라.

입출력 예제

m n board answer
4 5 [CCBDE, AAADE, AAABF, CCBBF] 14
6 6 [TTTANT, RRFACC, RRRFCC, TRRRAA, TTMMMF, TMMTTJ] 15

문제풀이

처음에는 진짜 이걸 어떻게 풀지? 하면서 고민을 엄청했던 것 같다.
몇시간을 고민했던 것 같은데, 집중을 하고 푸니까 그래도 풀리긴 했다..

  1. 주어진 배열을 아래와 같이 만들기 위해서 새롭게 board를 정해준다.
    [
        [C,A,A,C],
        [C,A,A,C],
        [B,A,A,B],
        [B,B,D,D],
        [F,F,E,E]
    ]
    
    이렇게 Board를 지정해놔야 후에 4블록을 제거하기위해 수월하다.
  2. newBoard에서 1,3에서 부터 시작해서 4개의 블록을 보기 시작하고,
    만약 4개블록이 모두 같다면 소문자로 바꿔준다(소문자로 바꾸는 이유는 중복으로 사용될수도 있기 때문.)
  3. 현재 newBoard에서 4블록을 모두 찾은 후에는 찾은 4블록을 제거해야한다. 4블록을 만족하면 소문자로 바꿨기 때문에, 소문자를 모두 제거한다.
    그리고, 소문자를 제거한 만큼 배열에 ""를 추가해준다.
    없어진 소문자의 갯수total에 더해서 없어진 블록을 계산해준다.
  4. 2,3번 과정을 계속해서 반복해야하는데, 여기서 만약 total값이 변하지 않으면 while문에 false를 넣어서 루프를 끝내준다.
function solution(m, n, board) {
  var answer = 0;
  let newBoard = [];
  for (let j = 0; j < n; j++) {
    let arr = [];
    for (let i = m - 1; i >= 0; i--) {
      arr.push(board[i][j]);
    }
    newBoard.push(arr);
  }
  answer = find(m, n, newBoard);
  return answer;
}

function find(m, n, board) {
  let isEnd = false;
  let total = 0;
  let i = 0;
  do {
    let check = total;
    for (let i = 1; i < n; i++) {
      for (let j = m - 2; j >= 0; j--) {
        let target = board[i][j].toLowerCase();
        if (
          target === board[i - 1][j + 1].toLowerCase() &&
          target === board[i - 1][j].toLowerCase() &&
          target === board[i][j + 1].toLowerCase()
        ) {
          board[i - 1][j] = board[i - 1][j].toLowerCase();
          board[i - 1][j + 1] = board[i - 1][j + 1].toLowerCase();
          board[i][j] = board[i][j].toLowerCase();
          board[i][j + 1] = board[i - 1][j + 1].toLowerCase();
        }
      }
    }
    board = board.map(e => {
      let count = 0;
      e = e.filter(el => {
        if (/[a-z]/.test(el)) {
          count++;
          return false;
        } else {
          return true;
        }
      });
      for (let i = 0; i < count; i++) {
        e.push("");
      }
      total += count;
      return e;
    });
    if (check === total) {
      isEnd = true;
    }
  } while (!isEnd);
  return total;
}

아쉬운 점 || 느낀 점

복잡해지니까, 집중력이 떨어지고 집중력이 떨어지니까 문제를 푸는데 시간이 오래 걸리는 것 같다.
지금 함수도 find함수만 만들어서 풀었는데, 이렇게 길게 한꺼번에 짜려고하다 보니까 복잡해져서 집중력이 떨어지는 것 같다.
맨날 다짐하지만, 지키지 못하는 약속 함수를 꼭 나눠서 만들자!