카카오 코딩테스트 | 프렌즈 4블록

Autumn·2020년 12월 28일
0

알고리즘

목록 보기
2/6
post-thumbnail

문제 바로가기

설계


코드

function solution(m, n, board) {
  let splitedBoard = board.map(e => e.split(''));
  let temp = [];
  let isFinished = false;
  
  const checkSameItems = (m, n, splitedBoard) => {
    for(let i = 0; i < m - 1; i++) {
      for(let j = 0; j < n - 1; j++) {
        const curr = splitedBoard[i][j];
        if(curr === 0) continue;
        if(curr === splitedBoard[i][j+1]) {
          if(curr === splitedBoard[i+1][j] && curr === splitedBoard[i+1][j+1]) {
            temp.push([i, j]);
            temp.push([i, j+1]);
            temp.push([i+1, j]);
            temp.push([i+1, j+1]);
          }
        }
      }
    }
    return (temp.length === 0 ? false : true)
  }
  
  const deleteItem = (splitedBoard, temp) => {
    temp.forEach(e => {
      const row = e[0];
      const col = e[1];
      splitedBoard[row][col] = 0;
    })
  }
  
  const changeRowCol = (matrix) => {
    // 아예 참조로 값을 연결해두면 col 배열에서 바꿨을 때 splitedBoard 도 바뀔듯 - 같이 안바뀜;
    return matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
  }
  
  const dropItem = (splitedBoard) => {
    const colArr = changeRowCol(splitedBoard);
    const filtered = colArr.map(col => col.filter(e => e !== 0));
    filtered.forEach(arr => {
      const toAdd = m - arr.length;
      for(let k = 0; k < toAdd; k++){
        arr.unshift(0); // 앞에 0으로 채워주기
      }
    })
    return changeRowCol(filtered) // 다시 col row 바꿔서 원래 모양대로 리턴
  }
  
  // -------------------------------- 실행부 ---------------------------------------
  
  while(isFinished === false) {
    const check = checkSameItems(m, n, splitedBoard);
    if (check === false) isFinished = true;
    
    deleteItem(splitedBoard, temp); // 터진거 0으로 바꾸기
    temp = []; // temp 초기화
    const dropped = dropItem(splitedBoard); // 빈자리에 아이템 땡겨오기
    splitedBoard = dropped;
  }
  
  // while문 밖에는 게임 종료 후 splitedBoard 배열에서 0의 개수 세서 정답으로 리턴하면 됨.
  let answer = 0;
  splitedBoard.forEach(arr => arr.forEach(e => {
    if(e === 0) answer +=1;
  }))
  
  return answer
}

풀이 방법

시작 전에!

  • 원본 배열을 수정하지 않기 위함이기도 하고, 또한 문제에서 주어진 board에는 문자열로 들어있기 때문에 문자열을 한글자씩 떨어뜨려 2차원 배열을 새로 만들어 문제를 해결한다.
  • 4블록이 완성되어 터진 아이템은 그 자리의 글자를 숫자 0으로 바꾼다.

함수

  • checkSameItems
    현재 아이템이 0이면 패스, 현재 아이템과 다음 아이템이 같은지 우선 확인하고, 같으면 아래 두 아이템과 같은지 확인. 해당 인덱스 4개를 temp 배열에 넣는다. 중복은 크게 신경쓰지 않았는데 중복을 고려해서 set을 사용해도 좋았을 것 같다. temp 배열의 길이로 터뜨릴 수 있는 같은 아이템이 있는지 체크.

  • deleteItem
    위에 temp 배열의 정보를 이용해 터진 아이템을 0으로 바꾸는 함수

  • changeRowCol
    아이템이 터진 자리에 다른 아이템이 떨어지는 것을 구현하기 편리하도록 행과 열을 바꾸는 함수

  • dropItem
    행과 열을 바꾸고 0이 아닌 값들을 모은 후 비어있는 칸의 개수만큼 앞쪽에 0을 넣어준다. (unshift) 그리고 다시 원래대로 행과 열을 바꾸어 리턴

실행부

isFinished 라는 변수에 처음에 false 값을 주어 같은 4개의 아이템이 있을 때는 계속 while문을 돌고, 같은 4개의 아이템이 없으면 true로 바꿔주어 반복문에서 빠져나온다. 그 후에 배열에서 0의 개수를 세어 정답으로 리턴.


생각해볼 점

설계한대로 코드는 잘 짰는데 행과 열을 바꾸는 함수 changeRowCol에서 좀 헤맸다. 처음 작성한 코드는 틀린 줄도 모르고 있다가 m, n의 값이 다른 경우에서 에러가 나서 알았다. 여러가지 시도를 해보다가 결국 이 함수만 stackoverflow에서 찾아서 긁어왔는데 혼자서 구현을 꼭 해봐야겠다는 생각이 들었다. 예전부터 2차원배열 정말 싫어했는데 ㅠㅡㅠ 행, 열 바꾸는 것도 계속 외면해왔는데 더이상 외면하면 안될 것 같은 생각이... 😩

무려 카카오 코테이고 이 때 출제되었던 문제들 중에서도 난이도가 높은 문제여서 지레 겁먹고 중간에 포기하고 싶었는데 풀어내서 뿌-듯! 잘 쓴 코드인지는 잘 모르겠지만 풀어냈다는 것에 스스로에게 박수를 👏👏👏 6개월 전의 나와 비교해서 엄청난 성장을 한 것 같다! 그 때는 한문제 가지고 1~2주 질질 끌면서 풀었는데 ㅎㅎㅎ 물론 지금도 이 한 문제 푸는 데에 몇시간 걸리긴 했지만 앞으로 더 잘 할 수 있을 것 같다는 느낌이 들어서 기분 좋게 오늘 문제 마무리~ 😎

profile
한 발짝씩 나아가는 중 〰 🍁 / 자잘한 기록은 아래 🏠 아이콘에 연결된 노션 페이지에 남기고 있어요 😎

0개의 댓글