카카오 - 추석 트래픽

아따맘마·2021년 1월 12일
0

알고리즘 - 카카오

목록 보기
7/19

문제

이번 추석에도 시스템 장애가 없는 명절을 보내고 싶은 어피치는 서버를 증설해야 할지 고민이다. 장애 대비용 서버 증설 여부를 결정하기 위해 작년 추석 기간인 9월 15일 로그 데이터를 분석한 후 초당 최대 처리량을 계산해보기로 했다. 초당 최대 처리량은 요청의 응답 완료 여부에 관계없이 임의 시간부터 1초(=1,000밀리초)간 처리하는 요청의 최대 개수를 의미한다.

입력

  • solution 함수에 전달되는 lines 배열은 N(1 ≦ N ≦ 2,000)개의 로그 문자열로 되어 있으며, 각 로그 문자열마다 요청에 대한 응답완료시간 S와 처리시간 T가 공백으로 구분되어 있다.
    *응답완료시간 S는 작년 추석인 2016년 9월 15일만 포함하여 고정 길이 2016-09-15 hh:mm:ss.sss 형식으로 되어 있다.
  • 처리시간 T는 0.1s, 0.312s, 2s 와 같이 최대 소수점 셋째 자리까지 기록하며 뒤에는 초 단위를 의미하는 s로 끝난다.
  • 예를 들어, 로그 문자열 2016-09-15 03:10:33.020 0.011s은 2016년 9월 15일 오전 3시 10분 33.010초부터 2016년 9월 15일 오전 3시 10분 33.020초까지 0.011초 동안 처리된 요청을 의미한다. (처리시간은 시작시간과 끝시간을 포함)
  • 서버에는 타임아웃이 3초로 적용되어 있기 때문에 처리시간은 0.001 ≦ T ≦ 3.000이다.
  • lines 배열은 응답완료시간 S를 기준으로 오름차순 정렬되어 있다.

출력

  • solution 함수에서는 로그 데이터 lines 배열에 대해 초당 최대 처리량을 리턴한다.

풀이

우선 입력 문자열을 파싱한다. 처음엔 ' '으로 파싱 후 시간 문자열은 ':'로 그리고 처리시간 T는 's'로 파싱하면 된다.(날짜 문자열은 필요없으니 제거)
로그 처리 시간이 겹치는 부분은 다음과 같이 했다.

로그 끝나는 시간인 end는 시작 시간, 끝시간을 포함해야 하므로 0.999초로 해줬다.
end - start + 0.001 = 1 초이므로.
단지 한가지 주의해야할 점은 seoul42에서 printf할 때 실수 출력부분 공부시 잠시 봤던 부분이지만, 프로그래밍에서 실수의 정확도(?)라고 해야하나, 다시 봐야하지만 IEEEM 뭐 어쩌구 저쩌구 에 대해서 생각이 나서, 혹시 몰라
begin - 0.0001보다 크거나 같게 하고
end + 0.0001보다 작거나 같게 했다.
그냥 begin, end로 제출해봤더니 틀리게 나오긴 했다.

코드

#include <string>
#include <vector>
#include <iostream>
#include <math.h>

using namespace std;

vector<string> ft_strtok(string str, char ch)
{
    vector<string> res;
    int start = 0;
    for (int i = 0; i < str.length(); i++) {
        if (str[i] == ch) {
            res.push_back(str.substr(start, i-start));  // 잘 체크하자
            start = i + 1;
        }
    }
    res.push_back(str.substr(start, str.length()));

    return res;
}
int solution(vector<string> lines) {
    int answer = 0;

    vector<pair<double, double>> time;

    for (int i = 0; i < lines.size(); i++)
    {
        vector<string> tmp = ft_strtok(lines[i], ' '); # 파싱1
        vector<string> temp = ft_strtok(tmp[1], ':'); # 파싱2

        double end = stod(temp[0]) * 3600 + stod(temp[1]) * 60 + stod(temp[2]); # 시간을 초단위로 변경(소수점도 있기에 double 변수로)
        double t = stod(ft_strtok(tmp[2], 's')[0]); (처리시간 T도 double 변수로)

        time.push_back(make_pair(end - t + 0.001, end));
    }
    
    for (int i = 0; i < time.size(); i++) {
        double begin = time[i].second;
        double end = begin + 0.999;

        int tmp = 0;

        for (int j = i; j < time.size(); j++) {
            if (time[j].first <= end + 0.0001 && time[j].second >= begin - 0.0001)
                tmp++;
        }

        if (answer < tmp)
            answer = tmp;
    }
    return answer;
}

# 테스터
int main()
{
    vector<string> lines;
    lines.push_back("2016-09-15 20:59:57.421 0.351s");
    lines.push_back("2016-09-15 20:59:58.233 1.181s");
    lines.push_back("2016-09-15 20:59:58.299 0.8s");
    lines.push_back("2016-09-15 20:59:58.688 1.041s");
    lines.push_back("2016-09-15 20:59:59.591 1.412s");
    lines.push_back("2016-09-15 21:00:00.464 1.466s");
    lines.push_back("2016-09-15 21:00:00.741 1.581s");
    lines.push_back("2016-09-15 21:00:00.748 2.31s");
    lines.push_back("2016-09-15 21:00:00.966 0.381s");
    lines.push_back("2016-09-15 21:00:02.066 2.62s");
    int n = solution(lines);
    cout << n;
}
profile
늦게 출발했지만 꾸준히 달려서 도착지점에 무사히 도달하자

0개의 댓글