프로그래머스 Level2 : 기능개발
프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.
또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.
먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.
제한 사항
- 작업의 개수(progresses, speeds배열의 길이)는 100개 이하입니다.
- 작업 진도는 100 미만의 자연수입니다.
- 작업 속도는 100 이하의 자연수입니다.
- 배포는 하루에 한 번만 할 수 있으며, 하루의 끝에 이루어진다고 가정합니다. 예를 들어 진도율이 95%인 작업의 개발 속도가 하루에 4%라면 배포는 2일 뒤에 이루어집니다.
입출력 예
progresses | speeds | return |
---|---|---|
[93,30,55] | [1,30,5] | [2,1] |
입출력 예 설명
첫 번째 기능은 93% 완료되어 있고 하루에 1%씩 작업이 가능하므로 7일간 작업 후 배포가 가능합니다. 두 번째 기능은 30%가 완료되어 있고 하루에 30%씩 작업이 가능하므로 3일간 작업 후 배포가 가능합니다. 하지만 이전 첫 번째 기능이 아직 완성된 상태가 아니기 때문에 첫 번째 기능이 배포되는 7일째 배포됩니다. 세 번째 기능은 55%가 완료되어 있고 하루에 5%씩 작업이 가능하므로 9일간 작업 후 배포가 가능합니다.
따라서 7일째에 2개의 기능, 9일째에 1개의 기능이 배포됩니다.
해설
처음에 개발하고, 그 후 배포하는 형태로 코드를 작성했다. 처음에 다음처럼 작성했는데, list(map(lambda))
도 동작이 iterable하므로 for
문과 같다고 생각하니 while
안에 for
문이 3개라 줄여봤다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def solution(progresses, speeds):
answer = []
while sum(speeds) != 0:
progresses = list(map(lambda x, y : x+y, progresses, speeds)) #하루 개발
if progresses[0] >= 100: #우선순위 높은 기능 개발 완료되면 배포
speeds = list(map(lambda x, y : 0 if x >= 100 else y, progresses, speeds))
idx = 0
for i in range(len(speeds)):
if speeds[i] == 0:
idx = i
else: break
total = idx + 1
progresses = progresses[idx+1:]#배포된 후 리스트에서 제거
speeds = speeds[idx+1:]
answer.append(total)
return answer
줄이고 나니까 개발하는 것도 하나의 for
문으로 작성할 수 없을까 고민해봤는데, 오히려 코드가 복잡해져서 접었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
def solution(progresses, speeds):
answer = []
while sum(speeds) != 0:
progresses = list(map(lambda x, y : x+y, progresses, speeds)) #하루 개발
if progresses[0] >= 100: #우선순위 높은 기능 개발 완료되면 배포
complete = 0
for i in progresses:
if i>= 100 : complete += 1
else: break
answer.append(complete)
progresses = progresses[complete:]#배포된 후 리스트에서 제거
speeds = speeds[complete:]
return answer
근데 다른사람 풀이를 보니까 대단하더라. 어떻게 생각해내는거지?
1
2
3
4
5
6
7
8
def solution(progresses, speeds):
Q=[]
for p, s in zip(progresses, speeds):
if len(Q)==0 or Q[-1][0]<-((p-100)//s):#(p-100)//s는 다 개발되기까지 걸리는 시간
Q.append([-((p-100)//s),1]) #다음 기능이 개발되지 않으면
else:
Q[-1][1]+=1 #다음 기능이 개발되었으면
return [q[1] for q in Q]
프로그래머스 Level2 : 다리를 지나는 트럭
트럭 여러 대가 강을 가로지르는 일 차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 트럭은 1초에 1만큼 움직이며, 다리 길이는 bridge_length이고 다리는 무게 weight까지 견딥니다. ※ 트럭이 다리에 완전히 오르지 않은 경우, 이 트럭의 무게는 고려하지 않습니다.
예를 들어, 길이가 2이고 10kg 무게를 견디는 다리가 있습니다. 무게가 [7, 4, 5, 6]kg인 트럭이 순서대로 최단 시간 안에 다리를 건너려면 다음과 같이 건너야 합니다.
경과 시간 | 다리를 지난 트럭 | 다리를 건너는 트럭 | 대기 트럭 |
---|---|---|---|
0 | [] | [] | [7,4,5,6] |
1~2 | [] | [7] | [4,5,6] |
3 | [7] | [4] | [5,6] |
4 | [7] | [4,5] | [6] |
5 | [7,4] | [5] | [6] |
6~7 | [7,4,5] | [6] | [] |
8 | [7,4,5,6] | [] | [] |
따라서, 모든 트럭이 다리를 지나려면 최소 8초가 걸립니다.
solution 함수의 매개변수로 다리 길이 bridge_length, 다리가 견딜 수 있는 무게 weight, 트럭별 무게 truck_weights가 주어집니다. 이때 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 return 하도록 solution 함수를 완성하세요.
제한 조건
- bridge_length는 1 이상 10,000 이하입니다.
- weight는 1 이상 10,000 이하입니다.
- truck_weights의 길이는 1 이상 10,000 이하입니다.
- 모든 트럭의 무게는 1 이상 weight 이하입니다.
입출력 예
bridge_length | weight | truck_weights | return |
---|---|---|---|
2 | 10 | [7,4,5,6] | 8 |
100 | 100 | [10] | 101 |
100 | 100 | [10,10,10,10,10,10,10,10,10,10] | 110 |
해설
코드를 작성해서 잘 돌아갔는데, 계속 시간초과가 떴다. sum
이 $O(n)$이라서 원래 사용하던 sum(bridge)
를 weight
관리로 바꿔주니 잘 돌아갔다. 근데 while
문이 좀 거슬렸다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def solution(bridge_length, weight, truck_weights):
bridge = [0] * bridge_length
origin = weight
num = 0
while True:
num += 1
weight += bridge.pop(0) #도착하면 무게 더해줌
if truck_weights !=[]:
if truck_weights[0] <= weight:
bridge.append(truck_weights.pop(0))
weight -= bridge[-1] #다리에 올라와 있으면 무게 빼줌
else: bridge.append(0)
if weight == origin: break #무게로 while문 관리
return num
다른 사람풀이를 참고하니, 아래처럼 써서 사용했다. 생각해보니 bridge
가 텅 비는 시점이 모든 트럭이 다리를 건넌 시점이랑 똑같더라.
1
2
3
4
5
6
7
8
9
10
11
12
def solution(bridge_length, weight, truck_weights):
bridge = [0] * bridge_length
num = 0
while bridge:
num += 1
weight += bridge.pop(0) #도착하면 무게 더해줌
if truck_weights !=[]:
if truck_weights[0] <= weight:
bridge.append(truck_weights.pop(0))
weight -= bridge[-1] #다리에 올라와 있으면 무게 빼줌
else: bridge.append(0)
return num
Leave a comment