[프로그래머스] 추석 트래픽

mokomoko·2022년 5월 27일

1. 문제


이번 추석에도 시스템 장애가 없는 명절을 보내고 싶은 어피치는 서버를 증설해야 할지 고민이다. 장애 대비용 서버 증설 여부를 결정하기 위해 작년 추석 기간인 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를 기준으로 오름차순 정렬되어 있다.

- 키워드

  • 특정 시간에서 탐색할 때 시작점에서 +0.999초를 더한 곳 까지 비교한다.
  • 비교하는 로그의 시작점과 끝점이 기준 시작점보다 앞서거나 끝점보다 뒤에 있으면 제외한다.

2. 풀이


java를 연습하기 위해 예전에 풀어보던 문제들을 다시 풀어보고 있다. Python으로는 참 쉬웠는데 말이지...

특정 1초 구간에 가장 처리가 많았던 구간의 로그 양을 출력해주면 된다.

나는 이 문제를 String -> 스플릿 후 계산 -> String 이 형태로 복잡하게 풀긴했지만....

다른 사람들의 풀이를 확인해보니 그냥 년,월,일,시간,분 을 모두 초로 바꿔버리고 풀어도 된다.

사실 그렇게 푸는 게 더 간단할 것이다.

다만, 로그의 크기가 다 다르고 시작점도 시간 순서가 아니기 때문에

시간 효율성을 잡겠다고 중간에 break는 걸면 안 된다.

3. 소스코드


# python
import decimal
def solution(lines):
	result = 0
	time_line = []
	for time in lines:
		part = time.split()
		part[1] = part[1].split(':')
		part[2] = part[2][:-1]
		right = ""
		for i in part[1]:
			right += i
		right = float(right)
		part[2] = float(part[2])
		left = right - part[2]
		if int(left)%100 > 90:
			left -= 40
		if int(left)%10000 > 9000:
			left -= 4000
		
		left = decimal.Decimal(str(left))+decimal.Decimal('0.001')
		time_line.append([left,right])

	for time in time_line:
		left,right = time[1],decimal.Decimal(str(time[1]))+decimal.Decimal('0.999')
		if int(right)%100 >= 60:
			right -= 60
			right += 100
		if int(right)%10000 >= 6000:
			right -= 6000
			right += 10000
		
		count = 0
		for log in time_line:
			if left <= log[0] <= right or left <= log[1] <= right or (log[0] <= left and right <= log[1]):
				count += 1
		if result < count:
			result = count

	return result
// java
import java.util.*;
import java.io.*;

class Solution {
    public static String timeToString(int year,int month,int day,int hour,int min, double sec){
        String start = ""+year+"-";
        if(month < 10) start += "0"+month+"-"; else start += month+"-";
        if(day < 10) start += "0"+day+" "; else start += day+" ";
        if(hour < 10) start += "0"+hour+":"; else start += hour+":";
        if(min < 10) start += "0"+min+":"; else start += min+":";
        if(sec < 10) start += "0"+sec; else start += sec;
        return start;
    }
    
    public static String startTime(String[] log){
        String[] date = log[0].split("-");
        int year=Integer.parseInt(date[0]),month=Integer.parseInt(date[1]),day=Integer.parseInt(date[2]);
        String[] time = log[1].split(":");
        int hour=Integer.parseInt(time[0]),min=Integer.parseInt(time[1]);
        double sec=Double.parseDouble(time[2]);
        String[] cost = log[2].split("s");
        double csec=Double.parseDouble(cost[0]) - 0.001;
        sec -= csec;
        if(sec < 0){ sec += 60;  min -= 1; }
        if(min < 0){ min += 60;  hour -= 1;}
        if (hour < 0){ hour += 24;  day -= 1;}
        if(day < 0){
            month -= 1;
            if(month == 2) day += 28;
            else if (month == 4 || month == 6 || month == 9 || month == 11) day += 30;
            else day += 31;
        }
        if(month < 0){ month += 13; year -= 1;}
        return timeToString(year,month,day,hour,min,sec);

    }
    public String oneSecond(String t){
        String[] log = t.split(" ");
        String[] date = log[0].split("-");
        int year=Integer.parseInt(date[0]),month=Integer.parseInt(date[1]),day=Integer.parseInt(date[2]);
        String[] time = log[1].split(":");
        int hour=Integer.parseInt(time[0]),min=Integer.parseInt(time[1]);
        double sec=Double.parseDouble(time[2]);
        sec += 0.999;
        if(sec > 60) {sec -= 60; min += 1; sec = Math.floor(sec * 1000) / 1000.0;}
        if(min > 60) {min -= 60; hour += 1;}
        if(hour > 24) {hour -= 24; day += 1;}
        if(month == 2 && day > 28) {month += 1; day -= 28;}
        else if((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) {month += 1; day -= 30;}
        else if(day > 31) {month += 1; day -= 31;}
        if(month > 12) {month -= 12; year += 1;}
        
        return timeToString(year,month,day,hour,min,sec);
        
    }
    
    public static boolean compare(String start,String end,String s,String e){
        if(start.compareTo(s) > 0 && start.compareTo(e) > 0) return false;
        else if(end.compareTo(s) < 0 && end.compareTo(e) < 0) return false;
        else return true;
    }
    
    public int solution(String[] lines) {
        String[] start = new String[lines.length];
        String[] end = new String[lines.length];
        int answer = 0;
        for(int i=0;i<lines.length;i++){
            String[] log = lines[i].split(" ");
            start[i] = startTime(log);
            end[i] = log[0]+" "+log[1];
        }
        for(int i=0;i<start.length;i++){
            int cnt = 1;
            for(int j=i+1;j<start.length;j++)
                if(compare(start[i],oneSecond(start[i]),start[j],end[j])) cnt++;

            answer = Math.max(answer,cnt);
            cnt = 1;
            for(int j=i+1;j<start.length;j++)
                if(compare(end[i],oneSecond(end[i]),start[j],end[j])) cnt++;

            answer = Math.max(answer,cnt);
        }
        return answer;
    }
}

4. 후기


java

python

과거에 풀던 문제들을 다시 풀어보니 막막할 때가 있는 거 같다.

내가 부족했던 부분들을 한 번씩 확인해봐야겠다.

뭣보다 java가 python에 비해 속도가 정말 월등하게 빠르다는 것을 느낀다.

0개의 댓글