반응형
코딩에 한시간 좀 넘은 듯 한데 생각보다 신입 코딩 테스트 치고는 난이도가 있는 문제인것 같다.
먼저 크게 검색->제거->이동(DropDown) 으로 행위를 나누었고, 2x2 동일한 블럭이 검색되지 않을때까지 매 라운드를 반복한다. 카카오에서 언급한 코드의 라인 수는 약 80~90라인인데 마지막에 리뷰하다 보니 다소 비효율적으로 짜여진 부분이 눈에 들어온다. 나중에 한번 시간나면 리팩터링도 해 봐야겠다.
- 보드판 복사
연산을 수행하고 결과를 만들 보드 객체를 별도로 생성(복제) 한다. - 2x2 동일 블럭 검색
검색된 블럭의 위치를 삭제 예정 리스트에 넣는다. - 동일 블럭 삭제(' ' 대체)
삭제 예정 리스트를 확인하며 블럭을 삭제한다. 검색과 삭제를 분리하지 않았을때 동시에 처리할 명확하고 간단한 방법이 문제 풀때 생각나지 않았으므로 따로 Task를 나누는 방식으로 해결했다. - 블럭 이동(DropDown)
삭제된 블럭이 생기면 해당 위치를 상단에 있는 블럭이 채우도록 한다. (DropDown) - 2x2 동일한 블럭이 검색되지 않을떄까지 라운드를 계속 반복한다.
package net.albear.codingtest.programmers;
import java.util.*;
// https://tech.kakao.com/2017/09/27/kakao-blind-recruitment-round-1/
// 프렌즈4블록(난이도: 상)
public class FriendsBlock {
public static void main(String[] args) throws Exception{
// String[] board = new String[]{"CCBDE","AAADE","AAABF","CCBBF"};
String[] board = new String[]{"TTTANT","RRFACC","RRRFCC","TRRRAA","TTMMMF","TMMTTJ"};
new FriendsBlock().solution(board.length, board[0].length(), board);
}
public int solution(int m, int n, String[] board) {
int answer = 0;
// 1. 결과를 계산할 새로운 배열에 값을 복사한다.
// 이떄 String 은 CharArray 형태로 변환하여 쉽게 탐색/수정 할 수 있도록 한다.
List<char[]> newBoard = new ArrayList<>();
for(String s: board){
newBoard.add(s.toCharArray());
}
printBoardLayout("최초 원본", newBoard);
// 전체 삭제된 블록 갯수
int totalRemoveBlockCount = 0;
// 하나의 Round에 삭제된 블록 갯수 (1라운드: 탐색->삭제->블록DropDown)
int currentRemoveBlockCount;
do {
List<Integer[]> matchedBlockLocations = new ArrayList<>();
for (int h = 0; h < newBoard.size(); h++) {
for (int w = 0; w < newBoard.get(h).length; w++) {
// 2x2 계산 안되는건 pass
if (h > m - 2 || w > n - 2){
continue;
}
if (scanBlocksFromBoard(h, w, newBoard)) {
matchedBlockLocations.add(new Integer[]{h, w});
}
}
}
// 블록 제거
currentRemoveBlockCount = removeSameBlocksFromBoard(newBoard, matchedBlockLocations);
// 삭제된 블록 print
printBoardLayout("삭제후", newBoard);
System.out.println("Current RemoveBlockCount > " + currentRemoveBlockCount);
// 더이상 삭제할 블록이 없다면 종료.
if (currentRemoveBlockCount == 0) break;
// 블록 DropDown
dropDownBlocksFromBoard(newBoard);
// Drop 후 블록 print
printBoardLayout("DropDown후", newBoard);
// 삭제한 블록 갯수 업데이트
totalRemoveBlockCount += currentRemoveBlockCount;
System.out.println();
}while(currentRemoveBlockCount > 0);
System.out.println("Total RemoveBlockCount > " + totalRemoveBlockCount);
return answer;
}
/**
* 2x2 블록 검색
*
* @param h
* @param w
* @param newBoard
* @return
*/
private boolean scanBlocksFromBoard(int h, int w, List<char[]> newBoard){
char n00 = newBoard.get(h)[w];
char n01 = newBoard.get(h)[w+1];
char n02 = newBoard.get(h+1)[w];
char n03 = newBoard.get(h+1)[w+1];
if(n00 == n01 && n01 == n02 && n02 == n03){
return true;
}else{
return false;
}
}
/**
* Board에서 2x2 동일한 블럭을 삭제한다.
*
* @param board
* @param matchedBlockLocations
* @return
*/
private int removeSameBlocksFromBoard(List<char[]> board, List<Integer[]> matchedBlockLocations){
int removeCount = 0;
for(Integer[] hwPoint : matchedBlockLocations){
int h = hwPoint[0];
int w = hwPoint[1];
if(board.get(h)[w] != ' '){ board.get(h)[w] = ' '; removeCount++; }
if(board.get(h)[w+1] != ' '){ board.get(h)[w+1] = ' '; removeCount++; }
if(board.get(h+1)[w] != ' '){ board.get(h+1)[w] = ' '; removeCount++; }
if(board.get(h+1)[w+1] != ' '){ board.get(h+1)[w+1] = ' '; removeCount++; }
}
return removeCount;
}
/**
* 아래가 비어있는 블록을 하단으로 이동한다.
*
* @param board
*/
private void dropDownBlocksFromBoard(List<char[]> board){
Queue<Integer> queue = new LinkedList<>();
for(int w=board.get(0).length-1; w>=0; w--){
for(int h=board.size()-1; h>=0; h--){
char curBlock = board.get(h)[w];
if(curBlock == ' '){
queue.add(h);
continue;
}else{
try{
// 이전에 빈블럭이 있었는지 확인해서 위치를 가져온다.
int emptyHeightIndex = queue.remove();
// 이번 빈블럭 위치에 현재 블럭을 넣고 현재 위치는 비워둔다.
board.get(emptyHeightIndex)[w] = curBlock;
board.get(h)[w] = ' ';
// 현재 위치가 이제 빈 블럭이므로 queue에 넣어준다.
queue.add(h);
}catch(NoSuchElementException e){ /* Exception 이 났다는건 하단에 빈블럭이 없다는 말이므로 옮길 필요가 없어 pass 한다. */ }
}
}
queue.clear();
}
}
/**
* 입력받은 board 객체의 블록들을 출력한다.
*
* @param title
* @param board
*/
private void printBoardLayout(String title, List<char[]> board){
System.out.println("===== "+title+" =====");
for (int i = 0; i < board.size(); i++) {
System.out.println(board.get(i));
}
}
}
반응형
'IT Tech > Dev-Tools' 카테고리의 다른 글
Intellij Auto package import (자동 패키지 import) 설정 (0) | 2020.10.01 |
---|---|
Intellij 컴파일시 인코딩 문제 한글 깨짐 현상 해결 (0) | 2020.10.01 |