준영이의 성장일기(FrontEnd)

프로그래머스 - 과제 진행하기 본문

코테 및 알고리즘

프로그래머스 - 과제 진행하기

Jay_Jung 2024. 9. 20. 19:29

<문제>

https://school.programmers.co.kr/learn/courses/30/lessons/176962?language=javascript

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

문제의 제한사항

3 ≤ plans의 길이 ≤ 1,000plans의 원소는 [name, start, playtime]의 구조로 이루어져 있습니다.

name : 과제의 이름을 의미합니다.
2 ≤ name의 길이 ≤ 10name은 알파벳 소문자로만 이루어져 있습니다. 또한 name이 중복되는 원소는 없습니다.
start : 과제의 시작 시각을 나타냅니다."hh:mm"의 형태로 "00:00" ~ "23:59" 사이의 시간값만 들어가 있습니다.
모든 과제의 시작 시각은 달라서 겹칠 일이 없습니다.과제는 "00:00" ... "23:59" 순으로 시작하면 됩니다.
즉, 시와 분의 값이 작을수록 더 빨리 시작한 과제입니다.playtime : 과제를 마치는데 걸리는 시간을 의미하며, 단위는 분입니다. 1 ≤ playtime ≤ 100playtime은 0으로 시작하지 않습니다.
배열은 시간순으로 정렬되어 있지 않을 수 있습니다.
진행중이던 과제가 끝나는 시각과 새로운 과제를 시작해야하는 시각이 같은 경우 진행중이던 과제는 끝난 것으로 판단합니다.

 

<문제 핵심>

이 문제는 로직의 흐름이 왜 이렇게 흘러가는지 파악해야한다.

 

일단 각 plans배열 요소마다 과목, 시작 시간, 소요시간 으로 구성되어 있었다. 일단 시간을 분으로 바꿔주는 함수를 적용하였다.

function timeToMin(time) {
  const [hh, mm] = time.split(':').map(Number);
  return hh * 60 + mm;
}

 

제일 중요했던 건 만약 기존의 태스크가 13:00에 끝나는 경우 새로운 태스크가 12:30에 시작한다면 기존의 태스크를 멈춘 다음 새로운 태스크를 진행해야한다. 이거는 문제 조건에 의거하면 알 수 있다.

 

  새로운 과제를 시작할 시각이 되었을 때, 기존에 진행 중이던 과제가 있다면 진행 중이던 과제를 멈추고 새로운 과제를 시작합니다

 

그리고 만약 12:30에 시작한 태스크가 40분 후에 끝나고 13:10에 시작하는 태스크가 있다고 해보자. 아까 멈췄던 13:00에 끝나는 태스크, 그리고 13:10에 시작하는 태스크 중 먼저 수행해야 할거는 새로 시작하는 태스크이다.

 

 

문제 조건

 

<문제 풀이과정 및 순서도>

 

1. 시간을 분으로 바꿔주는 함수를 구현한다.

function timeToMin(time) {
  const [hh, mm] = time.split(':').map(Number);
  return hh * 60 + mm;
}

 

2. 위에 설명한 로직의 흐름을 코드로 구현한다.

 

✅ 가장 빠른 시간에 시작하는 과제부터 차례대로 처리할 수 있도록 역순으로 정렬한다.

✅ 만약 새로 시작되는 과제가 이전 과제의 종료 시간보다 빨리 시작한다면, 그 과제의 종료 시간을 현재 과제의 소요 시간만큼 뒤로 미룬다.(이게 사실 문제의 핵심으로 새로 들어오는 과제가 끝나야 중단했던 과제를 진행할 수 있기 때문이고 또한 충돌 방지를 위해서)

✅ stack 배열은 과제가 언제 끝나는지를 관리해주기 위해 이용하기

function solution(plans) {
  const stack = [];
  //과제가 언제 종료되는지를 관리

  const sortedPlans = plans
    .map(([subject, time, count]) => [subject, timeToMin(time), Number(count)])
    .sort((a, b) => b[1] - a[1]);

  while (sortedPlans.length) {
    const [subject, time, count] = sortedPlans.pop()
    //가장 빨리 시작하는게 나올 것임
    stack.forEach((val, idx) => {
        if(time < val[1]) {
            stack[idx][1] += count; 
        }
    })    
        //idx는 첨에 0으로 시작할 것
    stack.push([subject, time+count]) 
    
  }

  const answer = stack.sort((a, b) => a[1] - b[1]).map(val => val[0]);
  return answer;
}

 

<전체 코드>

function timeToMin(time) {
  const [hh, mm] = time.split(':').map(Number);
  return hh * 60 + mm;
}

function solution(plans) {
  const stack = [];
  //과제가 언제 종료되는지를 관리

  const sortedPlans = plans
    .map(([subject, time, count]) => [subject, timeToMin(time), Number(count)])
    .sort((a, b) => b[1] - a[1]);

  while (sortedPlans.length) {
    const [subject, time, count] = sortedPlans.pop()
    //가장 빨리 시작하는게 나올 것임
    stack.forEach((val, idx) => {
        if(time < val[1]) {
            stack[idx][1] += count; 
        }
    })    
        //idx는 첨에 0으로 시작할 것
    stack.push([subject, time+count]) 
    
  }

  const answer = stack.sort((a, b) => a[1] - b[1]).map(val => val[0]);
  return answer;
}

'코테 및 알고리즘' 카테고리의 다른 글

백준 js, Python - N과M(5)  (3) 2024.09.26
프로그래머스 - 퍼즐 게임 챌린지  (0) 2024.09.24
백준 js 1063번  (2) 2024.09.18
백준 1183번 js  (0) 2024.09.08
프로그래머스 - 땅따먹기  (1) 2024.09.07