크레인 인형뽑기 게임

2019 카카오 겨울 인턴쉽 기출

  ·  3 min read

문제설명 #

죠르디가 만들려는 크레인 인형뽑기 게임은 아래와 같은 규칙을 따른다.1

  1. 게임 화면

    • 격자로 이루어진 정사각형 화면.
    • 격자 칸에는 인형(숫자로 표현) 또는 빈칸(0)이 있음.
  2. 게임 규칙

    • 크레인을 좌우로 움직여 지정된 열의 맨 위 인형을 집어 바구니에 담음.
    • 바구니에 같은 모양의 인형이 연속으로 쌓이면 터져서 사라짐.
    • 빈칸에서는 아무 일도 일어나지 않음.
    • 바구니는 무제한 크기.
  3. 입력 데이터

    • board: 게임 화면 상태를 나타내는 2차원 배열.
    • moves: 크레인 작동 위치를 나타내는 배열.
  4. 출력

    • 크레인 작동 결과 터져서 사라진 인형의 총 개수.

제약 조건

  • $5 \le N \le 30,\ 1 \le \text{moves} \le 1000$
  • $0 \le \text{board의 값} \le 100$

문제 나누기 #

  1. 주어진 vector를 다시 세로로 한줄씩 관리할 수 있는 형태 변경한다.
  2. moves의 원소의 값에 해당하는 위치의 가장 맨 위의 인형을 pop.
  3. pop한 인형을 바구니에 push
  4. 바구니에 서로 겹치는 인형이 있다면 소멸시킨다.

문제 해결하기 #

std::vector<std::vector<int>> vectorToStack(std::vector<std::vector<int>> board);
int getDoll(std::vector<std::vector<int>>& stack_board, int move);
void moveDollToBasket(std::vector<int> &basket, int doll);
void checkDuplicatedDoll(std::vector<int> &basket, int& answer);

각각 1, 2, 3, 4에 해당하는 기능을 함수로 작성하였다. 아래는 전체 코드이다.

전체코드 #

int solution(std::vector<std::vector<int>> board, std::vector<int> moves) {
    int answer = 0;
    std::vector<int> basket;
   	std::vector<std::vector<int>> stack_board = vectorToStack(board);
    for(const auto& move : moves){
        int doll = getDoll(stack_board, move);
        if(doll == 0) continue;
        moveDollToBasket(basket, doll);
        checkDuplicatedDoll(basket, answer);
    }
    return answer;
}

std::vector<std::vector<int>> vectorToStack(std::vector<std::vector<int>> board){
    std::vector<std::vector<int>> vertical_vector;
    for(int x = 0 ; x < board[0].size() ; x++){
        std::vector<int> temp_vector;
        for(int y = 0 ; y < board.size() ; y++){
            if(board[y][x] != 0) temp_vector.emplace_back(board[y][x]);
        }
        vertical_vector.emplace_back(temp_vector);
    }
    return vertical_vector;
}

int getDoll(std::vector<std::vector<int>>& stack_board, int move){
   	if(stack_board[move-1].empty()) return 0;
    int doll = stack_board[move-1][0];
    stack_board[move-1].erase(stack_board[move-1].begin());
    return doll;
}

void moveDollToBasket(std::vector<int> &basket, int doll){
    basket.emplace_back(doll);
}

void checkDuplicatedDoll(std::vector<int> &basket, int& answer){
    if(basket[basket.size()-1] == basket[basket.size()-2]){
        basket.erase(basket.end()-2,basket.end());
        answer += 2;
    }
}

레벨 1의 난도를 가지고 있는 무제라 쉽게 문제 나누기에서 계획한대로 쉽게 나눌 수 있었다. 인덱스 접근을 위해 std::stack<int> 형태가 아닌 바로 std::vector<int> 타입을 사용하였다.

풀이 개선하기 #

개선점

  1. stack을 이용하여 간단하게 변환할 수 있을것
  2. 소멸하는 과정에서 push하지 않고 top과 같으면 pop후 answer 값을 증가시킬것

기존에는 std::vector<std::vector<int> 타입을 이용하였으나 이제는 더 간단하고 문제에 의도로 보이는 std::vector<std::stack<int>>를 이용하여 문제 풀이를 개선하여볼 것이다. 또한 2번에서 설명하였듯이 push기능은 소멸되지 않을 때만 작동하도록 변경하겠다.

std::vector<std::stack<int>> vectorToStack(std::vector<std::vector<int>> board){
    std::vector<std::stack<int>> vertical_vector;
    for(int x = 0 ; x < board[0].size() ; x++){
        std::stack<int> temp_stack;
        for(int y = board.size()-1 ; y >= 0 ; y--){
            if(board[y][x] != 0) temp_stack.push(board[y][x]);
        }
        vertical_vector.emplace_back(temp_stack);
    }
    return vertical_vector;
}

스택은 LIFO이므로 y값은 역순으로 순회하도록 하였다.

int getDoll(std::vector<std::stack<int>>& stack_board, int move){
   	if(stack_board[move-1].empty()) return 0;
    int doll = stack_board[move-1].top();
    stack_board[move-1].pop();
    return doll;
}

void moveDollToBasket(std::stack<int> &basket, int doll, int& answer){
    if(!basket.empty() && basket.top() == doll){
        basket.pop();
        answer += 2;
        return;
    }
    basket.push(doll);
}
int solution(std::vector<std::vector<int>> board, std::vector<int> moves) {
    int answer = 0;
    std::stack<int> basket;
   	std::vector<std::stack<int>> stack_board = vectorToStack(board);
    for(const auto& move : moves){
        int doll = getDoll(stack_board, move);
        if(!doll) continue;
        moveDollToBasket(basket, doll, answer);
    }
    return answer;
}

References #


  1. “코딩테스트 연습 - 크레인 인형뽑기 게임,” 프로그래머스 스쿨. https://school.programmers.co.kr/learn/courses/30/lessons/64061 ↩︎