카카오 신입공채 1차 코딩테스트 문제4 셔틀버스 JAVA 예제

카카오톡 신입공채 1차 코딩 테스트 문제4 셔틀버스 JAVA 예제카카오톡 신입공채 1차 코딩 테스트 문제4 셔틀버스 JAVA 예제


카카오 신입공채 1차 코딩테스트 문제4 셔틀버스 JAVA 예제


문제설명

카카오에서는 무료 셔틀버스를 운행하기 때문에 판교역에서 편하게 사무실로 올 수 있다. 카카오의 직원은 서로를 ‘크루’라고 부르는데, 아침마다 많은 크루들이 이 셔틀을 이용하여 출근한다.


이 문제에서는 편의를 위해 셔틀은 다음과 같은 규칙으로 운행한다고 가정하자.


  • 셔틀은 09:00부터 총 n회 t분 간격으로 역에 도착하며, 하나의 셔틀에는 최대 m명의 승객이 탈 수 있다.
  • 셔틀은 도착했을 때 도착한 순간에 대기열에 선 크루까지 포함해서 대기 순서대로 태우고 바로 출발한다. 예를 들어 09:00에 도착한 셔틀은 자리가 있다면 09:00에 줄을 선 크루도 탈 수 있다.

일찍 나와서 셔틀을 기다리는 것이 귀찮았던 콘은, 일주일간의 집요한 관찰 끝에 어떤 크루가 몇 시에 셔틀 대기열에 도착하는지 알아냈다. 콘이 셔틀을 타고 사무실로 갈 수 있는 도착 시각 중 제일 늦은 시각을 구하여라.


단, 콘은 게으르기 때문에 같은 시각에 도착한 크루 중 대기열에서 제일 뒤에 선다. 또한, 모든 크루는 잠을 자야 하므로 23:59에 집에 돌아간다. 따라서 어떤 크루도 다음날 셔틀을 타는 일은 없다.


입력형식

셔틀 운행 횟수 n, 셔틀 운행 간격 t, 한 셔틀에 탈 수 있는 최대 크루 수 m, 크루가 대기열에 도착하는 시각을 모은 배열 timetable이 입력으로 주어진다.


  • 0 < n ≦ 10
  • 0 < t ≦ 60
  • 0 < m ≦ 45
  • timetable은 최소 길이 1이고 최대 길이 2000인 배열로, 하루 동안 크루가 대기열에 도착하는 시각이 HH:MM 형식으로 이루어져 있다.
  • 크루의 도착 시각 HH:MM은 00:01에서 23:59 사이이다.

출력형식

콘이 무사히 셔틀을 타고 사무실로 갈 수 있는 제일 늦은 도착 시각을 출력한다. 도착 시각은 HH:MM 형식이며, 00:00에서 23:59 사이의 값이 될 수 있다.

입출력 예제


문제해설

쉬워 보이는데 어려운 문제가 바로 이 문제였던 거 같네요. 당초 난이도를 ‘중’으로 두고 문제를 중간 즈음에 배치하였는데, 시간을 계산하는 부분에서 많은 분들이 어려워하셨던 거 같습니다.


예를 들어 2번 입출력 예제의 경우 ["09:10", "09:09", "08:00"]인데 이 경우 두 번째 버스는 9:10분에 출발하기 때문에 9:10분에 오면 되지 않느냐 많이들 혼동하셨을 거 같아요. 하지만 9:00에 오는 버스는 8:00에 대기하는 크루 1명만 탑승할 수 있고, 따라서 9:10 버스에는 남아 있는 두 명이 모두 타게 됩니다. 따라서 좀 더 이른 9:09에 와야 탑승할 수 있습니다.


전체 계산은 어렵지 않지만 이처럼 정확하게 시간 계산을 해야 하는 부분이 많고 마지막 버스 시간까지 빈틈없이 계산해야 해서 많은 분들이 실수를 한 거 같습니다. 이 문제는 정답률이 두 번째로 낮은 26.79%입니다.


문제출처 : http://tech.kakao.com/2017/09/27/kakao-blind-recruitment-round-1/

JAVA 예제


솔직히 말해서 개인적으로 이번 문제가 제일 어려웠습니다. 어떻게 억지로 풀기야 풀었지만, 깔끔하지 못해서 마음에 들지 않습니다. 로직도 if, else가 너무 많이 들어갔고, 시간 계산 때문에 "시:분"에 대한 단위 환산 처리까지 함께 고려하느라 논리적으로 로직이 깔끔한 모습은 아니였습니다. 조금더 고민하고 정갈하게 소스를 짤 수 있도록 더 노력해야 겠습니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import java.util.Arrays;
 
public class Bus {
 
    public static void main(String[] args) {
        System.out.println(getLastTime(115new String[]{"08:00""08:01""08:02""08:03"}));
        System.out.println(getLastTime(2102new String[]{"09:10""09:09""08:00"}));
        System.out.println(getLastTime(212new String[]{"09:00""09:00""09:00""09:00"}));
        System.out.println(getLastTime(115new String[]{"00:01""00:01""00:01""00:01""00:01"}));
        System.out.println(getLastTime(111new String[]{"23:59"}));
        System.out.println(getLastTime(106045new String[]{"23:59","23:59""23:59""23:59""23:59""23:59"
                , "23:59""23:59""23:59""23:59""23:59""23:59""23:59""23:59""23:59""23:59"}));
    }
    
    /**
     * 마지막으로 탈 수 있는 버스 시간 추출
     * @param n 금일 버스운행 횟수
     * @param t 버스운행 간격
     * @param m 한번에 태울 수 있는 사람 수
     * @param waitTime 줄서고 있는 사람들
     * @return 마지막으로 탈 수 있는 버스 시각
     */
    public static String getLastTime(int n, int t, int m, String[] waitTime) {
        String answer = "";
        
        // 버스 도착시간 계산
        String[] busTime = new String[n];
        for(int i = 0; i < n ; i++) {
            busTime[i] = getAddTime("09:00", t*i);
        }
        
        String lastBustTime = busTime[n-1];
        
        //대기자 명단을 먼저온 기준으로 정렬
        Arrays.sort(waitTime);
        
        int curPos = 0;
        int curAdded = 0;
        String busStop = "";
        for(int j = 0; j < busTime.length; j++) {
            busStop = busTime[j];
            curAdded = 0;
            // 순차적으로 버스가 들어옴을 for로 처리
            for(int k = curPos ; curPos < waitTime.length; k++) {
                // 현재 버스에 시간 이전에 도착한 사람이 있는 경우  && 현재 버스에  빈 자리가 있는 경우
                if(getMinLong(busStop)>=getMinLong(waitTime[k]) && curAdded < m ) {
                    answer = waitTime[curPos]; // 마지막 탑승 가능한 사람 도착 시간 입시저장
                    answer = getAddTime(answer, -1); // 마지막 탑승 가능자 보다 1분 빨리 오도록 임시시간 지정
                    curPos++;
                    curAdded++;
                    // curAdd < m 버스 자리가 여유있고, 마지막 탑승객이면 현재 버스 시간에 맞게 나감
                    if(j==busTime.length -1 && k == waitTime.length-1 && curAdded < m) {
                        answer = busTime[n-1];
                    }
                }
                else {
                    // 마지막 버스 인데 탑승객이 전부 못타는 경우 최종탑승자(answer)보다 빨리 와야 함
                    if(j==busTime.length-1 && curPos >= 1) {
                        // 마지막 탑승 가능한 사람 도착 시간 입시저장
                        answer = waitTime[curPos -1];
                        answer = getAddTime(answer, -1);    
                    }
                    break;
                }
            }
        }
        
        // 마지막 버스를 타도 여유가 있는 경우
        if("".equals(answer)||getMinLong(answer) > getMinLong(lastBustTime)) {
            answer = lastBustTime;
        }
        
        return answer;
    }
    
    /**
     * hh:mm의 String을 입력받아 addMin만큼 더한 시간 리턴
     * @param hhmm
     * @param addMin
     * @return hhmm분에 addMin분 을 합산한 시간
     */
    private static String getAddTime(String hhmm, int addMin) {
        long temp = getMinLong(hhmm);
        temp = temp + addMin;
        int hh = (int)temp/60;
        int mm = (int)temp%60;
        return String.format("%02d", hh)+":"+String.format("%02d", mm);
        
    }
    
    /**
     * hh:mm 의 스트링을 입력받아 long형태의 분으로 리턴
     * 입력 String 01:30, 출력 long 90
     * @param hhmm
     * @return long타입의 분
     */
    private static long getMinLong(String hhmm) {
        String arr[] = hhmm.split(":");
        int hh = Integer.parseInt(arr[0]);
        int mm = Integer.parseInt(arr[1]);
        return hh*60+mm;
    }
}
cs


문의 및 댓글 환영 :)

이 글을 공유하기

댓글

Email by JB FACTORY