Algorithm & Data Structure/Programmers

[Programmers]Python_기능개발

ju_young 2021. 1. 19. 10:43
728x90
문제

 

문제 설명

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

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

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

 

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

 

코드

 

시간, 개수 같이 계산
import math
def solution(progresses, speeds):
    tmps = []
    for progress, speed in zip(progresses, speeds):
        day = math.ceil((100 - progress) / speed) #걸리는 시간
        #첫 번째 배포일이거나 다음 개발 시간이 더 오래걸릴때
        if len(tmps) == 0 or tmps[-1][0] < day:
            tmps.append([day, 1])
        #다음 개발 시간이 더 작거나 같을때
        else:
            tmps[-1][1] += 1
    return [tmp[1] for tmp in tmps] #배포 기능 개수만 추가
from math import ceil
#Counter 사용
from collections import Counter
def solution(progresses, speeds):
    temp = []
    for progress, speed in zip(progresses, speeds):
        cur_day = ceil((100 - progress) / speed)
        if not temp or temp[-1] < cur_day :
            temp.append(cur_day)
        elif temp[-1] >= cur_day:
            temp.append(temp[-1])
            
    return list(Counter(temp).values())

 

시간, 개수 따로 계산
import math
from collections import deque
def solution(progresses, speeds):
    answer = []
    days = deque([])
    #걸리는 시간을 따로 저장
    for progress, speed in zip(progresses, speeds):
        rest_progress = 100 - progress
        rest_day = math.ceil(rest_progress / speed)
        days.append(rest_day)
        
    n = 1 #1개
    idx = 0 #index = 0부터 시작
    
    #answer 합이 기능 개수보다 작은 동안 반복
    while sum(answer) < len(days):     
        cur_day = days[idx] #현재 기능의 배포일
        for i in range(idx + 1, len(days)):
            #다음 기능의 개발 시간이 더 작거나 같다면 같이 배포
            if cur_day >= days[i]:
                n += 1
                idx += 1
            #개발 시간이 더 크다면 지금까지 같이 배포하는 기능 수 추가 후 초기화
            else:
                answer.append(n)
                n = 1
                idx += 1
                break
        #현재 기능부터 마지막 기능까지 모두 배포하는 경우
        else:
            answer.append(n)
        
    return answer

 

진행 과정

 

예제 #1

progresses = [95, 90, 99, 99, 80, 99]

speeds = [1, 1, 1, 1, 1, 1]

 

위에서 작성한 코드를 보면 시간, 개수를 따로 혹은 같이 계산하는 것을 따로 올린 것을 볼 수 있다. 이렇게 두 개의 코드를 따로 올린 것은 어떻게 생각하고 계산하느냐에 따라 코드가 얼마나 효율적이고 간결하게 표현될 수 있는지를 보여주는 문제이기 때문이다.

 

설명은 시간, 개수를 같이 계산한 간결한 코드로 진행하겠다.

 

먼저 각 기능 개발이 걸리는 시간은 "(100 - 현재 진행 작업 진도) - 속도" 이다. 이것만 알면 문제를 푸는데 어려움은 없을 것이다.

 

tmps 리스트에 개발이 걸리는 시간, 개수를 같이 추가하는데 만약 tmps가 비어있다면 가장 첫 번째 기능부터 시작하는 것이므로 (첫 번째 기능 개발이 걸리는 시간, 개수)를 무조건 추가해준다. 그리고 다음 기능 개발이 걸리는 시간과 비교하여 배포 기능 개수를 추가할 것인지 말 것인지를 판단한다.

 

처음에 튜플로 추가하고 싶은 충동이 들었다가 수정이 안되는 튜플의 특징 때문에 리스트로 추가해주었다.

 

여기까지가 시간, 개수를 같이 추가해주었을떄의 설명이다.

 

시간, 개수를 따로 생각했을때는 위 작성된 코드를 보듯이 아주 비효율적이다. 설명은 생략하겠다.

 

코드 진행은 다음과 같다.

 

1) tmps = [[5, 1]]


2) tmps = [[5, 1], [10, 1]]
3) tmps = [[5, 1], [10, 2]]
4) tmps = [[5, 1], [10, 3]]


5) tmps = [[5, 1], [10, 3], [20, 1]]
6) tmps = [[5, 1], [10, 3], [20, 2]]

728x90