[코딩테스트] Lv.2 기능개발

Keunyeong Lee·2022년 1월 19일
0

[코딩테스트]

목록 보기
6/11
post-thumbnail

☝🏽 문제

프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.

또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.

먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.

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

입출력 예

입출력 예 설명

입출력 예 #1

첫 번째 기능은 93% 완료되어 있고 하루에 1%씩 작업이 가능하므로 7일간 작업 후 배포가 가능합니다.
두 번째 기능은 30%가 완료되어 있고 하루에 30%씩 작업이 가능하므로 3일간 작업 후 배포가 가능합니다. 하지만 이전 첫 번째 기능이 아직 완성된 상태가 아니기 때문에 첫 번째 기능이 배포되는 7일째 배포됩니다.
세 번째 기능은 55%가 완료되어 있고 하루에 5%씩 작업이 가능하므로 9일간 작업 후 배포가 가능합니다.

따라서 7일째에 2개의 기능, 9일째에 1개의 기능이 배포됩니다.

입출력 예 #2

모든 기능이 하루에 1%씩 작업이 가능하므로, 작업이 끝나기까지 남은 일수는 각각 5일, 10일, 1일, 1일, 20일, 1일입니다. 어떤 기능이 먼저 완성되었더라도 앞에 있는 모든 기능이 완성되지 않으면 배포가 불가능합니다.

따라서 5일째에 1개의 기능, 10일째에 3개의 기능, 20일째에 2개의 기능이 배포됩니다.

🙋🏽‍♂️ 풀어보기!

function solution(progresses, speeds) {
  var answer = [];
  // 배포할때마다 제거해주기위해 수정할수 있도록 배열을 변수로 만들고
  let prog = [...progresses];
  let speedsArr = [...speeds];
  // 배포해야할 일이 사라질때까지 돌린다 ( 날짜가 간다는 개념 )
  while (prog.length !== 0) {
    // 바로 일 시작! 하루에 할수 있는 만큼 일을 시킨다.
    prog = prog.map((persent, dev) =>
      persent >= 100 ? persent : persent + speedsArr[dev]
    );
    // 완성된 작업들을 앞에부터 확인한다.
    // 앞에부터 완성된 작업이 있으면 배포가 준비됬다는 의미로 false를 넣어준다.
    // 앞부터 보다가 완성되지 않은 작업의 차례가 오면 스탑이 for 문을 넘겨 버린다.
    for (let i = 0; i < prog.length; i++) {
      if (prog[i] >= 100) {
        prog[i] = false;
      } else {
        break;
      }
    }
    // 모든 작업중 가장 첫번째 순서의 작업이 배포준비가 되었는지 확인하고
    if (prog[0]===false) {
      // 첫번째 작업이 배포 준비가 되었다면 
      // 배포되는 작업의 수를 카운트 할 준비
      let deployCount = 0;
      // 앞에부터 배포시킨다 배포되면 배열에서 뽑아버린다.
      // 앞부터 배포준비 된 작업만 배포하고
      // 앞에 배포 준비가 안되있으면 스탑
      while (prog[0] === false) {
        // 배포된 작업 제거
        prog.shift();
        // 배포되는 작업의 하루 작업량이 들어있는 배열의 값도 같이 삭제.
        speedsArr.shift();
        // 배포되는 작업의 수 카운트
        deployCount++;
      }
      // 하루에 배포된 작업의 수를 리턴할 배열에 push
      answer.push(deployCount);
    }
  }
  return answer;
}

🤔 이슈

  • 처음에는 27점?..

이유: 작업 배열만 뽑아나가고 작업량 배열을 그대로 두고 사용..

  • 두번째 57점..

이유: 문제가 stack/queue 인데 사용하지 않아서 그런가 하고.. 사용, 배열에서 제거할때 arr.shift() 사용

  • 드디어 100점

이유?: 작업량 배열도 shift() 사용.

👍 다른사람 풀이 중 내가 생각하는 베스트!

  • 많은 멋진 분들의 풀이
function solution(progresses, speeds) {
    let answer = [0];
    // 작업을 완료하여 배포까지 걸리는 날을 구함
  	// 나눴을때 소수점이 생기면 올림하여 배포일을 구함
    let days = progresses.map((progress, index) => Math.ceil((100 - progress) / speeds[index])); // ex - [2,3,1,3]
    // 맨앞부터 배포해야하므로 배포일 배열의 맨앞 배포일을 진행한 작업일로 설정
    let maxDay = days[0]; 
    // 배포할 작업의 수만큼 돌린다.
    for(let i = 0, j = 0; i< days.length; i++){
      	// 배포일 배열의 i번째가 현재 진행한 작업일 보다 작은지 확인 작으면 배포준비 완료!
        if(days[i] <= maxDay) {
            // 배포준비가 완료되었다면 
            // j 번째 작업배포일에 배포한 수량에 더하기 1 
            // ( 작업배포일은 일수 상관없이 배포한 날이면 되므로 answer에 배열 인덱스로 사용 )
            answer[j] += 1;
        } else {
            // 배포준비가 안되어있다면
            // 배포 가능한 날짜를 다음 작업 진행일로 설정.
            maxDay = days[i];
            // 작업배포일에 +1 ( answer 배열 인덱스에 +1 한것이다. )
            answer[++j] = 1;
        }
    }
    return answer;
}
  • 작업 배포에 걸리는 날짜를 구하고 맨앞 작업의 배포에 걸리는 날짜에 몇개를 배포하는지 구하는 방식

  • 가독성 최고! 이런것도 가능하네~ 싶음

⚙️ 리펙토링!

  • 절차적으로 생각하기 좋은 방식이라고 생각한다.
function solution(progresses, speeds) {
  var answer = [];
  // 배포할때마다 제거해주기위해 수정할수 있도록 배열을 변수로 만들고
  let prog = [...progresses];
  let speedsArr = [...speeds];
  // 배포해야할 일이 사라질때까지 돌린다 ( 날짜가 간다는 개념 )
  while (prog.length !== 0) {
    // 바로 일 시작! 하루에 할수 있는 만큼 일을 시킨다.
    prog = prog.map((persent, dev) =>
      persent >= 100 ? persent : persent + speedsArr[dev]
    );
    // 모든 작업중 가장 첫번째 순서의 작업이 배포준비(100보다크거나같음)가 되었는지 확인하고
    if (prog[0] >= 100) {
      // 첫번째 작업이 배포 준비가 되었다면 
      // 배포되는 작업의 수를 카운트 할 준비
      let deployCount = 0;
      // 앞에부터 배포시킨다 배포되면 배열에서 뽑아버린다.
      // 앞부터 배포준비 된 작업만 배포하고
      // 앞에 배포 준비가 안되있으면 스탑
      while (prog[0] >= 100) {
        // 배포된 작업 제거
        prog.shift();
        // 배포되는 작업의 하루 작업량이 들어있는 배열의 값도 같이 삭제.
        speedsArr.shift();
        // 배포되는 작업의 수 카운트
        deployCount++;
      }
      // 하루에 배포된 작업의 수를 리턴할 배열에 push
      answer.push(deployCount);
    }
  }
  return answer;
}
  • 쓸데없는 for문 제거.
profile
🏃🏽 동적인 개발자

0개의 댓글