[프로그래머스] 레벨3 (level3) 추석트래픽

2020년 06월 02일, 13:40

추석트래픽

문제설명

이번 추석에도 시스템 장애가 없는 명절을 보내고 싶은 어피치는 서버를 증설해야 할지 고민이다. 장애 대비용 서버 증설 여부를 결정하기 위해 작년 추석 기간인 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 배열에 대해 초당 최대 처리량을 리턴한다.

입출력 예제

예제1

  • 입력: [

    2016-09-15 01:00:04.001 2.0s, 2016-09-15 01:00:07.000 2s ]

  • 출력: 1

예제2

  • 입력: [

    2016-09-15 01:00:04.002 2.0s, 2016-09-15 01:00:07.000 2s ]

  • 출력: 2

설명: 처리시간은 시작시간과 끝시간을 포함하므로 첫 번째 로그는 01:00:02.003 ~ 01:00:04.002에서 2초 동안 처리되었으며, 두 번째 로그는 01:00:05.001 ~ 01:00:07.000에서 2초 동안 처리된다. 따라서, 첫 번째 로그가 끝나는 시점과 두 번째 로그가 시작하는 시점의 구간인 01:00:04.002 ~ 01:00:05.001 1초 동안 최대 2개가 된다.

예제3

  • 입력: [

    2016-09-15 20:59:57.421 0.351s, 2016-09-15 20:59:58.233 1.181s, 2016-09-15 20:59:58.299 0.8s, 2016-09-15 20:59:58.688 1.041s, 2016-09-15 20:59:59.591 1.412s, 2016-09-15 21:00:00.464 1.466s, 2016-09-15 21:00:00.741 1.581s, 2016-09-15 21:00:00.748 2.31s, 2016-09-15 21:00:00.966 0.381s, 2016-09-15 21:00:02.066 2.62s ]

  • 출력: 7

  • 설명: 아래 타임라인 그림에서 빨간색으로 표시된 1초 각 구간의 처리량을 구해보면 (1)은 4개, (2)는 7개, (3)는 2개임을 알 수 있다. 따라서 초당 최대 처리량은 7이 되며, 동일한 최대 처리량을 갖는 1초 구간은 여러 개 존재할 수 있으므로 이 문제에서는 구간이 아닌 개수만 출력한다.

chosuk-traffic

문제 설명

레벨3 문제라서 그런지 뭔가 더 어렵게 느껴졌..(그리고 어렵다.)
문제 이해도 힘든편이였다. 그리고 가장 힘들었던 부분은 처리시간에 시작,끝이 포함되는 것이였다.
아직도 사실 잘 이해가 가지 않는다.. 진짜 너무 어렵다..

  1. Date를 통해 getTime()으로 millsecond를 반환하여
    lines를 {start, end}값으로 변환.(어차피 9-15일에 대해서만 계산하니까 값을 줄이기 위해 전역변수 de를 선언해서 빼줌.)
    시작시간,끝시간을 포함하니까 start를 구해주는 과정에서 +1을 해줘야함.
  2. start, end를 기준점으로 잡아서 포함되는 line들을 체크.
    1. 포함되는 시간은 1초를 더하는 것이지만, 시작시간과 끝시간을 포함하니까 +999.
    2. 포함되는 line들의 수를 count
    3. start를 기준으로 한 line count의 최댓값 , end를 기준으로 한 line count의 최댓값 중 max값을 answer로 리턴.
const de = new Date("2016-09-14 23:59:57").getTime();

function solution(lines) {
  var answer = 0;
  let hashs = makeHashArr(lines);
  // console.log(hashs)
  let starts = hashs.map(e => e.start);
  let ends = hashs.map(e => e.end);
  let startMax = 0;
  let endMax = 0;
  ends.forEach(end => {
    let count = 0;
    hashs.forEach(e => {
      if (checkTime(e, end)) {
        count++;
      }
    });
    endMax = Math.max(endMax, count);
  });
  starts.forEach(start => {
    let count = 0;
    hashs.forEach(e => {
      if (checkTime(e, start)) {
        count++;
      }
    });
    startMax = Math.max(startMax, count);
  });
  // console.log(startMax,endMax);
  answer = Math.max(startMax, endMax);
  return answer;
}

function makeHash(line) {
  const splited = line.split(" ");
  const date = new Date(`${splited[0]} ${splited[1]}`).getTime() - de;
  const execute = parseFloat(splited[2]) * 1000;

  return { start: date + 1 - execute, end: date };
}

function makeHashArr(lines) {
  return lines.map(e => makeHash(e));
}

function checkTime(hash, time) {
  if (hash.start < time && hash.end < time) {
    return false;
  } else if (hash.start > time + 999 && hash.end > time + 999) {
    return false;
  }
  return true;
}

/*
임의 시간부터 1초

*/

아쉬운 점 || 느낀 점

레벨3부터는 문제 자체도 복잡해지고, 조건들도 더 복잡해지는 것 같다.
이해하는 과정도 힘들고, 이해를 했다고 생각했는데 여러 조건들을 이해를 못해서 틀리는 것 같다.
이런 부분을 갈수록 줄여야하는데 쉽지않다.. ㅠㅠ