https://school.programmers.co.kr/learn/courses/30/lessons/176962#
1번째 풀이
1. plans의 start, playtime 시간문자열을 숫자로 변환한뒤, 그 시간에 따라 sort한다
2. 맨 처음 과제를 stack에 넣고 진행한다
3. 앞의 과제가 끝나는 시간 <= 다음 과제가 시작하는 시간이면 앞의과제는 완료되었고 answer에 과제이름을 넣는다.
4. 앞의 과제가 끝나는 시간 > 다음과제가 시작하는 시간이면, 앞의과제는 remained에 넣는다 (이때 playtime 남은 시간 = 앞 과제하는데 걸리는 시간 - (뒤 과제 시작시간 - 앞 과제시작시간) 으로 계산한다.)
5. 3번의 앞과제가 이미 다 끝났을때 remained남은과제가 남아있고 뒤 과제시작시간이 아직 안 됬을때 remained에서 뒤 과제를 빼서 stack에 넣고 뒤 과제를 마저진행한다.
6. 남은 과제를 하다가 끝나면 3번처럼 answer에 과제이름을 넣고, 미완료하면 다시 남은시간을 계산한뒤 remained에 넣는다.
이렇게 stack에 과제가 있을때까지 순환을 한뒤, 맨 마지막에 남은 remained과제를 뒤에서 하나씩 pop해서 answer에 넣어준다.
제출전 테스트케이스는 다 통과했지만
제출 후 케이스는 1,2, 14, 15, 16, 18, 19, 22, 23, 24만 통과하고 나머지는 실패ㅠ
function convertNum(str) {
return Number(str.split(':').join(''));
}
function convertClock(num) {
const lastTwo = num % 100;
if (lastTwo < 60) {
return num;
}
let division = Math.floor(lastTwo / 60);
let remain = lastTwo % 60;
return Math.floor(num / 100)*100 + 100*division + remain;
}
function solution(plans) {
var answer = [];
const stack = [];
const remained = [];
let nowTime = plans[0][1]; // 맨 처음 시작 시각
// 시간을 숫자로 변환후 시간에 따라 sort
let sortedPlans = plans.map(p => [p[0], convertNum(p[1]), convertNum(p[2])]).sort((a, b) => a[1] - b[1]);
// 맨 처음 과제 stack에 넣기
stack.push(sortedPlans.shift());
// 스케쥴대로 진행
while(stack.length) {
const curr = sortedPlans.shift();
if (!curr) {
answer.push(stack.shift()[0]);
break;
}
const [prevName, prevStart, prevPlaytime] = stack.shift();
// 전 과제가 끝날시각
const prevFinishTime = convertClock(prevStart + prevPlaytime);
// 완료시
if (prevFinishTime <= curr[1]) {
stack.shift();
answer.push(prevName); // 끝낸과제 올리기
nowTime += prevPlaytime;
// remained한게 없음 바로 다음 과제로 넘어간다
if (!remained.length) {
stack.push(curr);
nowTime = curr[1];
} else {
// remained한게 있고
// 다음 과제까지 시간이 남으면 remained를 진행
if (nowTime < curr[1]) {
const [name, remainedTime] = remained.pop();
stack.push([name, nowTime, remainedTime]);
sortedPlans.unshift(curr); // 다시 넣기
}
// 다음과제까지 시간이 없으면 바로 다음 과제 진행
else {
stack.push(curr);
}
}
}
// 미완료
else {
// stack에서 빼서 remained에 넣고, stack에는 그 다음 과제를 넣는다
stack.pop();
remained.push([prevName, prevPlaytime - (curr[1] - prevStart)]);
nowTime = curr[1];
stack.push(curr);
}
}
// 남은것들 완료
while (remained.length) {
answer.push(remained.pop()[0]);
}
return answer;
}
2번째 풀이
처음에는 convertClock 함수를 만들어서시간을 60분법으로 변환해줬는데 생각해보니 컴퓨터 입장에선 이렇게 할 필요 없었다.
그냥 split(':')한뒤 split()[0] * 60 + split()[1] 이렇게 timestamp 숫자로 시간비교를 하니 올 통과.
function convertNum(str) {
const [h, m] = str.split(':').map(e => Number(e));
return h*60 + m;
}
function solution(plans) {
var answer = [];
const stack = [];
const remained = [];
let nowTime = plans[0][1]; // 맨 처음 시작 시각
// 시간을 숫자로 변환후 시간에 따라 sort
let sortedPlans = plans.map(p => [p[0], convertNum(p[1]), Number(p[2])]).sort((a, b) => a[1] - b[1]);
console.log(sortedPlans)
// 맨 처음 과제 stack에 넣기
stack.push(sortedPlans.shift());
// 스케쥴대로 진행
while(stack.length) {
const curr = sortedPlans.shift();
if (!curr) {
answer.push(stack.shift()[0]);
break;
}
const [prevName, prevStart, prevPlaytime] = stack.shift();
// 전 과제가 끝날시각
const prevFinishTime = prevStart + prevPlaytime;
// 완료시
if (prevFinishTime <= curr[1]) {
stack.shift();
answer.push(prevName); // 끝낸과제 올리기
nowTime += prevPlaytime;
// remained한게 없음 바로 다음 과제로 넘어간다
if (!remained.length) {
stack.push(curr);
nowTime = curr[1];
} else {
// remained한게 있고
// 다음 과제까지 시간이 남으면 remained를 진행
if (nowTime < curr[1]) {
const [name, remainedTime] = remained.pop();
stack.push([name, nowTime, remainedTime]);
sortedPlans.unshift(curr); // 다시 넣기
}
// 다음과제까지 시간이 없으면 바로 다음 과제 진행
else {
stack.push(curr);
}
}
}
// 미완료
else {
// stack에서 빼서 remained에 넣고, stack에는 그 다음 과제를 넣는다
stack.pop();
remained.push([prevName, prevPlaytime - (curr[1] - prevStart)]);
nowTime = curr[1];
stack.push(curr);
}
}
// 남은것들 완료
while (remained.length) {
answer.push(remained.pop()[0]);
}
return answer;
}
수정
- 가독성을 위해 [0]이런 magic number사용 자제
- 배열말고 obj으로 풀면 가독성향상
- plans: 앞으로 해야할 과제
- stack: 진행중인 과제
function convertNum(str) {
const [h, m] = str.split(':').map(e => Number(e));
return h*60 + m;
}
function solution(plans) {
// 시간을 숫자로 변환후 시간에 따라 sort
plans = plans.map(([name, start, playtime]) => {
return {
name,
start: convertNum(start),
playtime: Number(playtime)
}
}).sort((a, b) => a.start - b.start);
var answer = [];
const stack = [];
const remained = [];
let currTime = plans[0].start; // 맨 처음 시작 시각
// 맨 처음 과제 stack에 넣기
stack.push(plans.shift());
while(true) {
if (plans.length && stack.length) {
const currPlan = stack[0];
const nextPlan = plans[0];
// 현재과제 이미 완료
if (currTime + currPlan.playtime <= nextPlan.start) {
answer.push(stack.shift().name);
currTime += currPlan.playtime;
}
// 현재과제 미완료시 남은시간 다시 계산해서 stack에 넣기
else {
currPlan.playtime -= nextPlan.start - currTime;
currTime = nextPlan.start;
stack.unshift(plans.shift());
}
}
// 진행중인 과제가 없을때 다음 과제를 진행
else if (plans.length) {
const newPlan = plans.shift();
stack.push(newPlan);
currTime = newPlan.start; // 시간업뎃
} else if (stack.length) {
answer.push(stack.shift().name);
} else {
break;
}
}
return answer;
}
'알고리즘' 카테고리의 다른 글
[프로그래머스 LV2] 무인도 여행 (0) | 2023.08.22 |
---|---|
[프로그래머스 LV2] 광물캐기 (0) | 2023.08.22 |
[프로그래머스] 덧칠하기 (0) | 2023.08.07 |
[프로그래머스] 한 번만 등장한 문자 (0) | 2023.07.27 |
[프로그래머스] 귤 고르기 (0) | 2023.07.18 |