[programmers 45] 기능개발

박예슬·2022년 9월 4일
0

문제설명

프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.
또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.
먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.

제한 사항

  • 작업의 개수(progresses, speeds배열의 길이)는 100개 이하입니다.
  • 작업 진도는 100 미만의 자연수입니다.
  • 작업 속도는 100 이하의 자연수입니다.
  • 배포는 하루에 한 번만 할 수 있으며, 하루의 끝에 이루어진다고 가정합니다. 예를 들어 진도율이 95%인 작업의 개발 속도가 하루에 4%라면 배포는 2일 뒤에 이루어집니다.

My solution

// 💡 문제 분석 💡
// 스택/큐 이용해서 풀기 : 먼저들어간게 먼저 나와야함 -> 큐, 배열이용(데이터가 100개이하)
// In : 작업의진도(자연수배열), 개발속도(자연수배열) Out : 배포시 몇개배포(자연수배열)
// 하루마다 현재의 진도에 개발속도를 더해줘야함
// 작업진도 제일 처음에 있는 요소가 100이 되면 배포 
// 배포시 그 다음것이 100인지 확인 : 100이면 같이 배포, count++ / 아니면 배포 x
// 각 배포시마다 count 수 out 배열에 넣어주기

function solution(progresses, speeds) {
    let answer = [];

    while (progresses.length !== 0) {  // 모든 요소가 다 배포될때까지 반복

        let count = 0;  // 배포되는 것 개수

        progresses = progresses.map((v, idx) => {   // 하루마다 각 진행도 업그레이드
            return v += speeds[idx];
        });

        while (progresses[0] >= 100) {  // 제일 첫번째 요소가 진행도 100 이상일경우 배포 반복
            progresses.shift();
            speeds.shift();
            count++;
        }

        if (count > 0) answer.push(count);  // count 가 0 이 아니면 배포진행했다는 것
    }

    return answer;
}

큐의 linked list 를 이용해서 풀려고했는데, 데이터가 많지가 않아서 그냥 배열로 구현했다.
실제로 걸리는 시간을 보니 문제가 없었다.

...

처음에 3개만 통과하고 7개에서 실패가 떴다.
한참 눈빠져라 코드를 훑고나서야 진행도 100이상인 경우 shift 해주는 곳에서
speeds 배열은 빼주지 않았던 것을 발견...
sppeds.shift() 코드를 추가해주니까 바로 성공!

...

하루마다 각 진행도를 업그레이드 하는 부분에서 map 이 아닌 아래 코드와 같이 for문으로 작성했었는데,

for (let i = 0; i < progresses.length; i++) {
  	if (progresses[i] < 100) progresses[i] += speeds[i];
}

map 을 사용하는 방식을로 하고싶어서 변경했다.
현 코드는 진행도가 100이상이어도 계속 더해주고 있는데, 지금 문제의 조건에선 문제가 없지만
만약에 제한사항이 추가가 된다면(?)
100 이상은 진행되지 않게 코드를 추가해줘야겠다.

효율성은 비슷했다.


Others

function solution(progresses, speeds) {
    let answer = [0];
    let days = progresses.map((progress, index) => Math.ceil((100 - progress) / speeds[index]));
    let maxDay = days[0];

    for(let i = 0, j = 0; i< days.length; i++){
        if(days[i] <= maxDay) {
            answer[j] += 1;
        } else {
            maxDay = days[i];
            answer[++j] = 1;
        }
    }

    return answer;
}

💡 생각의 전환!!

  1. 남은 일수를 count 하는 방식으로 진행
  2. 각 작업마다 소요되는 일수를 담은 배열을 만든다 : days
  3. 처음엔, days 배열의 0번째 요소가 maxDay
    : 뒤에 작업들이 얼마나 걸리든 현재 maxDay 만큼은 진행돼야 함
  4. days 배열의 요소를 돌면서, 현재의 maxDay보다 작거나 같은 것일 때는 answer 현재 index의 숫자를 ++ 해주기
    : 그 뒤에있는 다른 작업들이 걸리는 일수가 maxDay보다 작거나 같은 경우는 현재것을 작업하는동안 이미 작업이 다 끝났다는 경우니까, 현재것이 배포되면 이것들도 연달아 배포되어야 함
  5. 만약 그 다음 것이 소요되는 일수가 maxDay 보다 크면, 작업을 더 진행해야 하고, 거기서 해당날의 배포가 끝난것
    👉 배포하는 것이 다른 날이 되는거니까 answer의 index 값을 하나 증가해주고, 해당 인덱스 1부터 시작
    👉 mayDay가 새롭게 현재의 작업 일수가 됨

소요시간은 비슷했다.


Reference

profile
공부중인 개발자

0개의 댓글