2018 KAKAO BLIND RECRUITMENT
[1차] 추석 트래픽
로직
1. 입력받은 요청들을 밀리초로 변환하여 저장
2. 슬라이딩 윈도우 기법을 활용하여 1초씩 확인하는데, 초당 처리량이 바뀌는 포인트는 처리가 시작되는 시작지점 & 처리가 끝나는 끝지점 두 부분이므로 그 두부분에서 1초짜리 윈도우를 만들어 확인한다.
3. 윈도우 안에 들어가는 경우의 수는
3-1. 요청의 끝이 윈도우 안쪽에 들어있는 경우
3-2. 요청의 시작이 윈도우 안쪽에 들어있는 경우
3-3. 요청이 윈도우를 포함하는 경우
의 세가지 경우의 수이므로, 이에 따라 연산하여 최대값을 리턴한다.
1. 입력받은 요청들을 밀리초로 변환하여 저장
작년 추석 기간인 9월 15일 로그 데이터를 분석한 후 초당 최대 처리량을 계산해보기로 했다.
라는 조건이 있기때문에, 들어오는 로그에서 2016-09-15는 모두 동일하므로 신경쓸 필요가 없다. 따라서 앞부분은 버리고, 뒤쪽의 시간만 뽑아서 Time 객체를 활용하여 밀리초로 변환한다.
private static void parse(String[] lines) {
StringTokenizer st;
for (String l : lines) {
st = new StringTokenizer(l);
st.nextToken(); // 9월 15일 데이터라 앞쪽 로그는 필요없음
reqs.add(new Req(st.nextToken(), st.nextToken()));
}
}
static class Ms {
long ms;
public Ms(Time time, String ms) {
this.ms = time.getTime() + Long.parseLong(ms);
}
public Ms(long ms) {
this.ms = ms;
}
}
2. 슬라이딩 윈도우 기법을 활용하여 1초씩 확인하는데, 초당 처리량이 바뀌는 포인트는 처리가 시작되는 시작지점 & 처리가 끝나는 끝지점 두 부분이므로 그 두부분에서 1초짜리 윈도우를 만들어 확인한다.
private static boolean isIn(Req r, long startWindow) {
long endWindow = startWindow + 999; // 처리시간이 시작시간과 끝 시간을 포함하는 1초이기때문에 999초 더해줘야한다(1000초 더하면 1.001)
return (r.end.ms >= startWindow && r.end.ms <= endWindow)
|| (r.start.ms >= startWindow && r.start.ms <= endWindow)
|| (r.start.ms <= startWindow && r.end.ms >= endWindow);
}
static class Req {
Ms start;
Ms end;
long process;
public Req(String end, String process) {
this.end = new Ms(Time.valueOf(end.substring(0, 8)), end.substring(9));
this.process = (long) (Double.parseDouble(process.substring(0, process.length() - 1)) * 1000);
this.start = new Ms(this.end.ms - this.process + 1);
}
}
3. 윈도우 안에 들어가는 경우의 수는
3-1. 요청의 끝이 윈도우 안쪽에 들어있는 경우
3-2. 요청의 시작이 윈도우 안쪽에 들어있는 경우
3-3. 요청이 윈도우를 포함하는 경우
private static boolean isIn(Req r, long startWindow) {
long endWindow = startWindow + 999; // 처리시간이 시작시간과 끝 시간을 포함하는 1초이기때문에 999초 더해줘야한다(1000초 더하면 1.001)
return (r.end.ms >= startWindow && r.end.ms <= endWindow)
|| (r.start.ms >= startWindow && r.start.ms <= endWindow)
|| (r.start.ms <= startWindow && r.end.ms >= endWindow);
}
의 세가지 경우의 수이므로, 이에 따라 연산하여 최대값을 리턴한다.
private static int solution(String[] lines) {
parse(lines);
check();
return ans;
}
private static void check() {
for (Req r : reqs) {
ans = Math.max(count(r), ans);
}
}
코드 전문은 아래와 같습니다.
import java.sql.*;
import java.util.*;
class Solution {
private static List<Req> reqs = new ArrayList<>();
private static int ans;
public int solution(String[] lines) {
parse(lines);
check();
return ans;
}
private static void check() {
for (Req r : reqs) {
ans = Math.max(count(r), ans);
}
}
private static int count(Req window) {
int s = 0;
int e = 0;
for (Req r : reqs) {
if (isIn(r, window.start.ms)) {
s++;
}
if (isIn(r, window.end.ms)) {
e++;
}
}
return Math.max(s, e);
}
private static boolean isIn(Req r, long startWindow) {
long endWindow = startWindow + 999; // 처리시간이 시작시간과 끝 시간을 포함하는 1초이기때문에 999초 더해줘야한다(1000초 더하면 1.001)
return (r.end.ms >= startWindow && r.end.ms <= endWindow)
|| (r.start.ms >= startWindow && r.start.ms <= endWindow)
|| (r.start.ms <= startWindow && r.end.ms >= endWindow);
}
private static void parse(String[] lines) {
StringTokenizer st;
for (String l : lines) {
st = new StringTokenizer(l);
st.nextToken(); // 9월 15일 데이터라 앞쪽 로그는 필요없음
reqs.add(new Req(st.nextToken(), st.nextToken()));
}
}
static class Req {
Ms start;
Ms end;
long process;
public Req(String end, String process) {
this.end = new Ms(Time.valueOf(end.substring(0, 8)), end.substring(9));
this.process = (long) (Double.parseDouble(process.substring(0, process.length() - 1)) * 1000);
this.start = new Ms(this.end.ms - this.process + 1);
}
}
static class Ms {
long ms;
public Ms(Time time, String ms) {
this.ms = time.getTime() + Long.parseLong(ms);
}
public Ms(long ms) {
this.ms = ms;
}
}
}
'알고리즘 > 프로그래머스' 카테고리의 다른 글
프로그래머스 괄호 변환 (JAVA) (0) | 2021.06.08 |
---|---|
프로그래머스 오픈채팅방 (JAVA) (0) | 2021.06.07 |
프로그래머스 무지의 먹방 라이브 (JAVA) (0) | 2021.05.12 |
프로그래머스 뉴스 클러스터링 (JAVA) (0) | 2021.05.12 |
프로그래머스 신규 아이디 추천 (JAVA) (0) | 2021.05.05 |