본문으로 바로가기

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;
		}
	}
}