프로그래머스 - Java - 1 - 크레인 인형뽑기 게임
서론
제목의 의미는 [사이트 - 언어 - Level - 테스트 이름] 입니다.
코딩테스트를 처음 해봐서 1레벨 자바로 해봤습니다.
처음 코드 실행으로는 테스트 케이스 1개의 정답밖에 안 나와서 제출했는데 다른 테스트 케이스에서는 우수수 틀렸습니다.
빨간 네모 : 언어를 선택합니다.
초록 네모 : 문제설명입니다.
파란 네모 : 문제를 푸는 코드 입력란입니다.
주황 네모 : 노란네모의 '코드 실행' 버튼을 누르면 결과가 나옵니다.
빨간 네모 : 제출 후 채점입니다.
문제
인형뽑기 기능이 있고 오른쪽의 스택구조의 통에 하나씩 넣습니다.
이때 같은 두개의 인형이 만나면 애니팡처럼 사라집니다.
크레인을 모두 작동시킨 후 터트려져 사라진 인형의 개수를 return 하는 문제입니다.
[제한사항]
- board 배열은 2차원 배열로 크기는 "5 x 5" 이상 "30 x 30" 이하입니다.
- board의 각 칸에는 0 이상 100 이하인 정수가 담겨있습니다.
- 0은 빈 칸을 나타냅니다.
- 1 ~ 100의 각 숫자는 각기 다른 인형의 모양을 의미하며 같은 숫자는 같은 모양의 인형을 나타냅니다.
- moves 배열의 크기는 1 이상 1,000 이하입니다.
- moves 배열 각 원소들의 값은 1 이상이며 board 배열의 가로 크기 이하인 자연수입니다.
입출력 예
board | moves | result |
[[0,0,0,0,0],[0,0,1,0,3],[0,2,5,0,1],[4,2,4,4,2],[3,5,1,3,1]] | [1,5,3,5,1,2,1,4] | 4 |
풀이
public static int solution(int[][] board, int[] moves) {
int answer = 0;
int[] itemStack = new int[board.length * board[0].length]; // 꺼낸 인형이 담기는 칸
int lastStack = 0; // 마지막 인형 위치
for (int i=0; i<moves.length; i++){ // 크레인 위치
int move = moves[i]-1;
for (int j=0; j<board.length; j++){ // 위치만큼
int item = board[j][move]; //인형
if(item!=0) {
if(lastStack != 0 && itemStack[lastStack-1] == item){ // 인형 터짐
itemStack[lastStack] = 0;
board[j][move] = 0;
lastStack -= 1;
answer += 2;
} else { //인형 저장
itemStack[lastStack] = item;
board[j][move] = 0;
lastStack += 1;
}
break;
}
}
}
return answer;
}
맨 처음에는 결과값 answer 만 있어서 인형을 담을 int[] itemStack과 itemStack 안에서 마지막 인형의 위치를 저장할 lastStack를 만듭니다.
- 문제에 2차원 배열 크기가 고정이 아니기 때문에 board.length * board[0].length 로 총 몇 칸인지 계산합니다.
- itemStack가 없어도 마지막 위치를 구할 수 있지만 그럼 0 부터 거슬러 올라가야 하기 때문에 만들어줍니다.
첫 번째 for문은 크레인이 움직이는 moves.length만큼 반복하기 위해 만들었습니다.
- move 변수는 moves[i] 그대로 사용하면 1
5까지 들어오기 때문에 배열에 맞게 04로 바꿔서 사용하기 위해 만들었습니다.
- move 변수는 moves[i] 그대로 사용하면 1
1 입력받은 board는 아래와 같습니다.
- 처음에 이 부분이 헷갈려서 직접 프로젝트에 넣을 때 이해됐습니다.
int[][] board = {{0, 0, 0, 0, 0}, {0, 0, 1, 0, 3}, {0, 2, 5, 0, 1}, {4, 2, 4, 4, 2}, {3, 5, 1, 3, 1}};
2 두 번째 for문이 인형을 옮기는 기능입니다.
- board.length는 위 배열에서 세로로 몇 개인지 입니다. 예시로 int[3][5]에서 3을 return해줍니다.
- board[j][move]에서 move는 for문 밖에 있기 때문에 [0, 3] [1, 3] [2, 3] [3, 3] 이런 식으로 세로로 위에서부터 검사합니다.
- if(item!=0)는 제한사항에 '0은 빈칸을 나타냅니다.'라고 되어있기 때문에 아무 행동을 하지 않습니다.
if문으로 같은 인형이면 지울지 아니면 인형을 넣을지 결정합니다.
- 먼저 인형을 넣고 체크해도 되지만 같은 인형이라면 넣고 지우는 2번의 행동이 불필요하기 늘어나서 저는 먼저 지웠습니다.
- if문에서 lastStack != 0는 첫 번째 집은 인형이라면 무조건 저장하기 때문에 사용했습니다.
- if문에서 itemStack[lastStack-1] == item는 현재 집은 인형과 마지막에 들어 있는 인형을 비교합니다.
- lastStack != 0가 있기 때문에 lastStack-1에서 -1이 되는 오류를 방지할 수 있었습니다.
- itemStack[lastStack] = 0; 현재 저장된 인형을 지웁니다. 인형 저장을 먼저 했다면 lastStack-1의 인형까지 두 번 지워야 합니다.
- board[j][move] = 0; 인형을 꺼냈기 때문에 인형이 있던 자리를 0으로 비워줍니다.
- lastStack -= 1; 인형이 지워졌기 때문에 -1 해줍니다. 인형 저장을 먼저 했다면 -2 입니다.
- answer += 2; 결과로 return할 터진 인형의 개수입니다. 지운거 1개 뽑은 거 1개 총 2개를 더해줍니다.
- 이제는 else 부분입니다.
- itemStack[lastStack] = item; 꺼낸 인형을 저장합니다.
- board[j][move] = 0; 인형을 꺼냈기 때문에 인형이 있던 자리를 0으로 비워줍니다.
- lastStack += 1; 인형이 저장되었기 때문에 +1 해줍니다.
후기
해본 결과 다른 테스트는 입력이 어떻게 되는 건지 알기 힘들고 사이트 자체에서는 디버깅이 힘들어서 저는 따로 프로젝트를 생성해서 확인했습니다.
게다가 코딩테스트를 처음 해서인지 문제가 명확하지 않아서인지 이해를 잘못해서 시간이 많이 지체되었습니다.
몇몇 테스트의 시간이 만족스럽지 않네요. 옮긴 인형이 많아서일까요? ㅠㅠㅠ
1 level의 문제는 풀고보니 어렵지 않고 실제 코딩테스트라면 빨리 푸는게 중요하겠습니다.