99클럽 코테 스터디 8/99일차 TIL #기능개발도움말(미들러)
- -
문제:기능개발
출처: 프로그래머스
https://school.programmers.co.kr/learn/courses/30/lessons/42586
1. 문제 설명
프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.
또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.
먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.
제한 사항
- 작업의 개수(progresses, speeds배열의 길이)는 100개 이하입니다.
- 작업 진도는 100 미만의 자연수입니다.
- 작업 속도는 100 이하의 자연수입니다.
- 배포는 하루에 한 번만 할 수 있으며, 하루의 끝에 이루어진다고 가정합니다.
예를 들어 진도율이 95%인 작업의 개발 속도가 하루에 4%라면 배포는 2일 뒤에 이루어집니다.
2. 문제 해석
진도가 100일때 서비스 반영 가능
progress: 먼저 배포되어야 하는 순서임
speeds: 개발 속도
각 배포마다 몇 개의 기능이 배포되는지
ex)
progresses: [93, 30, 55] | speeds: [1, 30, 5]
1-> 7일 후 배포 가능
2-> 3일 후 배포 가능 -> 1번 기다려야함
30->9일 후 배포 가능 -> 7일 후 1, 2 완료 후 배포
return: [2, 1]
3. 문제 풀이
풀이 (1) 100/100
1. 예상 완료 기간을 이용해서 데이터를 일단 만들기(list 형식)
93, 1 => 100-93 = 7. =? 1*n => 7
30, 30 => 100-30 = 70 -> 30*n => 3
(100 - progress) % speed 가 0인 경우는 (100 - progress) // speed : 몫으로
(100 - progress) % speed 가 0이 아닌 경우는 (100 - progress) // speed+1 : 몫 +1
2. 생성된 리스트를 순회하면서 앞의 값과 현재 값을 비교하여 return 값을 형성
- cnt: 몇개의 작업을 한번에 처리할 지
- 임시 값을 하나 설정하고(이전 값) 그 값과 현재 값을 비교:
이전값 >= 현재값 : 기다려야 하는 상황, cnt += 1
이전값 < 현재값: 안기다려도 되는 상황: 앞의 cnt를 answer에 append, cnt를 초기화
def solution(progresses, speeds):
counts = len(progresses)
left_days = []
for i in range(counts):
left_day = 100-int(progresses[i])
speed = speeds[i]
if left_day % speed != 0:
day = left_day // speed +1
else:
day = left_day // speed
left_days.append(day)
print(left_days)
answer = []
cnt = 0
tmp_day = left_days[0]
for k, j in enumerate(left_days):
if j <= tmp_day:
cnt+=1
else:
answer.append(cnt)
tmp_day = left_days[k]
cnt = 1
answer.append(cnt)
return answer
테스트 1 〉 | 통과 (0.01ms, 10.2MB) |
테스트 2 〉 | 통과 (0.04ms, 10.4MB) |
테스트 3 〉 | 통과 (0.04ms, 10.2MB) |
테스트 4 〉 | 통과 (0.02ms, 10.3MB) |
테스트 5 〉 | 통과 (0.01ms, 10.3MB) |
테스트 6 〉 | 통과 (0.02ms, 10.2MB) |
테스트 7 〉 | 통과 (0.06ms, 10.1MB) |
테스트 8 〉 | 통과 (0.02ms, 10.2MB) |
테스트 9 〉 | 통과 (0.03ms, 10.1MB) |
테스트 10 〉 | 통과 (0.03ms, 10.2MB) |
테스트 11 〉 | 통과 (0.01ms, 10.2MB) |
테스트 1 〉 | 통과 (0.01ms, 10.2MB) |
테스트 2 〉 | 통과 (0.04ms, 10.4MB) |
테스트 3 〉 | 통과 (0.04ms, 10.2MB) |
테스트 4 〉 | 통과 (0.02ms, 10.3MB) |
테스트 5 〉 | 통과 (0.01ms, 10.3MB) |
테스트 6 〉 | 통과 (0.02ms, 10.2MB) |
테스트 7 〉 | 통과 (0.06ms, 10.1MB) |
테스트 8 〉 | 통과 (0.02ms, 10.2MB) |
테스트 9 〉 | 통과 (0.03ms, 10.1MB) |
테스트 10 〉 | 통과 (0.03ms, 10.2MB) |
테스트 11 〉 | 통과 (0.01ms, 10.2MB) |
2중 for문이 없어서 딱히 연산 속도의 문제는 없었다.
코드를 다 작성하고 for문이 각각 돌고 있어서 한 번에 합치는게 조금 더 좋다고 생각이 들었다.
문제 풀이 당시에는 시간 내 푸는게 목적이었어서 pass 했던 부분.
풀이 (2) 100/100
위 부분 말고도 다른 부분 줄일 만한게 있나 싶어 GPT 형님께 질문한 결과 수정된 코드는 다음과 같다.
def solution(progresses, speeds):
from math import ceil
# Calculate the remaining days for each task to complete
left_days = [ceil((100 - p) / s) for p, s in zip(progresses, speeds)]
# List to store the answer
answer = []
# Initialize the first task's completion day and a counter
current_max_day = left_days[0]
count = 1
# Iterate over the remaining days to count batches
for day in left_days[1:]:
if day <= current_max_day:
count += 1
else:
answer.append(count)
current_max_day = day
count = 1
# Append the last count
answer.append(count)
return answer
기존에 left_days 라고 명명한 list를 list comprehension + ceil + zip으로 바로 끝냈다.
이런거 연습 많이 해야함..
left_days = [ceil((100 - p) / s) for p, s in zip(progresses, speeds)]
ceil
ceil을 활용하게 되면 소숫점 올림을 해서 나머지 조건문을 한 번에 처리 가능하다.
그리고 for 문을 돌 때 progresses[i], speeds[i] 부분을 한번에 처리하기 위해 zip으로 리스트 자료형을 묶었다.
4. 주요 코드 및 정리
4.1 enumerate()
for i, j in enumerate(list): 리스트의 값을 가져오는 동시에 인덱스값도 같이 return 되는 반복문 형태.
앞의 값이 인덱스, 뒤의 값이 리스트 값.
4.2 python 올림 내림 반올림 함수, ceil(), floor(), round()
각 함수 사용을 위해 import math 또는 from math import ceil, floor 사용 (round는 자체 내장 함수로 import 불필요)
ceil(): 올림
floor(): 버림
round(): 반올림
from math import ceil, floor
print(100/2.2)
>> 45.45454545454545
print(ceil(100/2.2))
>> 46
print(floor(100/2.2))
>> 45
print(round(100/2.2))
>> 45
이번에 공부하면서 알게 된게 round() 함수를 쓸 때 홀수, 짝수인 경우 반올림이 다르게 들어가는 것을 알게 되었다.(충격)
모든 소숫점에 대해서 그런것은 아니고 0.5에서 문제가 있던 것이다.
print(round(1.5))
>> 2
print(round(2.5))
>> 2
print(round(3.5))
>> 4
print(round(4.5))
>> 4
print(round(5.5))
>> 6
round()함수는 홀수의 경우 0.5를 올림을, 짝수의 경우 0.5를 버림을 하는 식의 반올림이 진행된다.(왜이랩)?
ChatGPT의 답변은 다음과 같다.
Python의 round 함수는 반올림할 때 "짝수 쪽으로" 반올림하는 규칙을 따릅니다. 이 방법은 "은행가의 반올림" 또는 "가우스 반올림"이라고도 불리며, 통계적으로 더 정확한 결과를 얻기 위해 사용됩니다.
이 방법에서는 .5 값을 가장 가까운 짝수로 반올림합니다. 따라서 다음과 같은 결과가 나옵니다:
- round(1.5)는 2 (가장 가까운 짝수)
- round(2.5)는 2 (가장 가까운 짝수)
- round(3.5)는 4 (가장 가까운 짝수)
- round(4.5)는 4 (가장 가까운 짝수)
- round(5.5)는 6 (가장 가까운 짝수)
이 규칙은 데이터의 편향을 줄이기 위해 사용되며, 특히 많은 수의 데이터를 반올림할 때 유용합니다.
정확하게는 짝수쪽으로 반올림을 하는 규칙이고 이게 가우스 반올림이라고 한다.
참고로 한국어로 이걸 사사오입이라고 하는 사람들도 있던데 사사오입은 0부터 4까지 내림, 5부터 9까지 올림을 의미하는 말이다
'Career > Coding Test' 카테고리의 다른 글
99클럽 코테 스터디 10/99일차 TIL #이중우선순위큐(미들러) (0) | 2024.07.31 |
---|---|
99클럽 코테 스터디 9/99일차 TIL #더 맵게(미들러) (0) | 2024.07.30 |
99클럽 코테 스터디 7/99일차 TIL #하노이의 탑(미들러) (0) | 2024.07.28 |
99클럽 코테 스터디 6/99일차 TIL #의상 (0) | 2024.07.27 |
99클럽 코테 스터디 5/99일차 TIL #전화번호 목록(비기너) (0) | 2024.07.26 |
소중한 공감 감사합니다