개발자를 희망하는 죠르디가 카카오에 면접을 보러 왔습니다.
코로나 바이러스 감염 예방을 위해 응시자들은 거리를 둬서 대기를 해야하는데 개발 직군 면접인 만큼
아래와 같은 규칙으로 대기실에 거리를 두고 앉도록 안내하고 있습니다.
- 대기실은 5개이며, 각 대기실은 5x5 크기입니다.
- 거리두기를 위하여 응시자들 끼리는 맨해튼 거리1가 2 이하로 앉지 말아 주세요.
- 단 응시자가 앉아있는 자리 사이가 파티션으로 막혀 있을 경우에는 허용합니다.
예를 들어,
5개의 대기실을 본 죠르디는 각 대기실에서 응시자들이 거리두기를 잘 기키고 있는지 알고 싶어졌습니다. 자리에 앉아있는 응시자들의 정보와 대기실 구조를 대기실별로 담은 2차원 문자열 배열 places
가 매개변수로 주어집니다. 각 대기실별로 거리두기를 지키고 있으면 1을, 한 명이라도 지키지 않고 있으면 0을 배열에 담아 return 하도록 solution 함수를 완성해 주세요.
places
의 행 길이(대기실 개수) = 5places
의 각 행은 하나의 대기실 구조를 나타냅니다.places
의 열 길이(대기실 세로 길이) = 5P
,O
,X
로 이루어진 문자열입니다.places
원소의 길이(대기실 가로 길이) = 5P
는 응시자가 앉아있는 자리를 의미합니다.O
는 빈 테이블을 의미합니다.X
는 파티션을 의미합니다.places
에 담겨 있는 5개 대기실의 순서대로, 거리두기 준수 여부를 차례대로 배열에 담습니다.단계를 가지고 접근했어요.
- 주어진
place
별로 거리두기를 지켰는지 확인- 먼저 각
P
의 위치를 구함- 순회하면서 조건을 확인
3-1. 거리가2
초과는 무시
3-2. 거리가2
이하인 경우, 가로로 일직선인지, 세로로 일직선인지, 아니면 대각선으로 위치한지 확인
3-3. 그 사이에X
가 있다면 무시- 조건을 확인해서
true
면1
아니면0
추가
단계적 설계를 거치니 작성 속도는 다소 느리지만 버그 잡기가 훨씬 수월했어요. 실제 테스트에서도 이를 활용할 수 있을까요? 아니지, 활용할 수 있게끔 해봐야겠죠 ㅎㅎ.
import java.util.ArrayList;
import java.util.List;
// 1. 대기실은 5개이며, 각 대기실은 5x5 크기입니다.
// 2. 거리두기를 위하여 응시자들 끼리는 맨해튼 거리1가 2 이하로 앉지 말아 주세요.
// 3. 단 응시자가 앉아있는 자리 사이가 파티션으로 막혀 있을 경우에는 허용합니다.
// 4. 응시자 P, 빈 테이블 O, 파티션 X
public class Solution {
private static int TILE_SIZE = 5;
private static char PEOPLE = 'P';
private static char PARTITION = 'X';
private static char TABLE = 'O';
private class Point {
public final int y, x;
public Point(int y, int x) {
this.y = y;
this.x = x;
}
}
public int[] solution(String[][] places) {
int[] answer = new int[places.length];
for (int index = 0; index < places.length; ++index) {
String[] place = places[index];
answer[index] = (isRightPlace(place)) ? 1 : 0;
}
return answer;
}
private boolean isRightPlace(String[] place) {
List<Point> people = getPeoples(place);
for(int index = 0; index < people.size(); ++index){
Point person1 = people.get(index);
for(int index2 = index + 1; index2 < people.size(); ++index2){
Point person2 = people.get(index2);
if(2 < getdistance(person1.y, person1.x, person2.y, person2.x)){
continue;
}
if(isBlocked(place, person1.y, person1.x, person2.y, person2.x)){
continue;
}
return false;
}
}
return true;
}
private List<Point> getPeoples(String[] place) {
List<Point> ret = new ArrayList<Point>();
for (int y = 0; y < place.length; ++y) {
for (int x = 0; x < TILE_SIZE; ++x) {
if (place[y].charAt(x) == PEOPLE) {
ret.add(new Point(y, x));
}
}
}
return ret;
}
private int getdistance(int y1, int x1, int y2, int x2) {
return Math.abs(y1 - y2) + Math.abs(x1 - x2);
}
// NOTE : 거리가 2이하라면 두 사이간의 타일 크기도 2 X 2입니다.
// P가 있는 곳을 제외한 위치에 X가 둘 다 있으면 true를 반환합니다.
private boolean isBlocked(String[] place, int y1, int x1, int y2, int x2) {
if(y1 == y2 && x1 == x2){
return false;
}
if(y1 == y2){
return (place[y1].charAt((x1 + x2) >> 1) == PARTITION);
}
if(x1 == x2){
return (place[(y1 + y2) >> 1].charAt(x1) == PARTITION);
}
char tile1 = place[y1].charAt(x2);
char tile2 = place[y2].charAt(x1);
return (tile1 == PARTITION) && (tile2 == PARTITION);
}
}