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

mokomoko·2022년 5월 27일
0

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개의 댓글