본문 바로가기

CodingTest/Programmers

[ 프로그래머스 ] 기능개발

/  제출  1  /

from collections import deque
import math
def solution(progresses, speeds):
    answer = []
    remain = deque(list(map(lambda x:100-x,progresses)))
    speed = deque(speeds)
    date = 0
    keep = 0
    while remain:
        date += math.ceil(remain.popleft() / speed.popleft())
        keep += 1
        while remain:
            if (remain[0]-date*speed[0]) <= 0:
                remain.popleft()
                speed.popleft()
                keep += 1
            else:
                break
        answer.append(keep)
        keep = 0
        
    return answer

 

채점 결과
정확성: 45.5
합계: 45.5 / 100.0
테스트케이스 2, 3, 4, 7, 8, 9 실패 


흐으.. 맞을 줄 알았는데 안 되네요. 잘 접근했다고 생각했는데.. 

speed 를 그 때 그 때 계산해주니 복잡해져서 눈에도 잘 안 들어옵니다.. 다시 정리해서 풀어보겠습니다.
 

/  다른 사람 아이디어  /

  1. 초기 상태 => results = []
  2. 현재 진도율 93%, 증가 진도율 1% => 총 7일 소요 => 신규 추가 => results = [[7]]
  3. 현재 진도율 30%, 증가 진도율 30% => 총 3일 소요 => 7과 비교(요소 추가) => results = [[7, 3]]
  4. 현재 진도율 55%, 증가 진도율 5% => 총 9일 소요 => 7과 비교(배열 추가) =>results = [[7, 3], [9]]
  5. 총 결과의 길이를 반환 => results.map(result => result.length) => [2, 1]

와.. 정말 간결하고 좋다.. 어떻게 이런 아이디어를..?! ㅠㅜㅜ

구현해봤습니다. 그런데 사실 이 그대로는 아니고 내가 기존에 한 걸 수정한 느낌으로 갔습니다. 

 

/  2 번째 풀이  /

from collections import deque
import math
def solution(progresses, speeds):
    answer = []
    remain = list(map(lambda x:100-x,progresses))
    for i in range(len(speeds)):
        remain[i] = math.ceil(remain[i]/speeds[i])

    remain = deque(remain)
    while remain:
        cur = remain.popleft()
        print(cur)
        keep = 1
        while remain:
            if remain[0] <= cur:
                remain.popleft()
                keep += 1
            else:
                break
        answer.append(keep)
        
    return answer

/  남의 풀이  /

 

from math import ceil

def solution(progresses, speeds):
    daysLeft = list(map(lambda x: (ceil((100 - progresses[x]) / speeds[x])), range(len(progresses))))
    count = 1
    retList = []

    for i in range(len(daysLeft)):
        try:
            if daysLeft[i] < daysLeft[i + 1]:
                retList.append(count)
                count = 1
            else:
                daysLeft[i + 1] = daysLeft[i]
                count += 1
        except IndexError:
            retList.append(count)

    return retList

 

딱 이 방식이 제가 구현하고 싶었던 아이디어라서 다른 우수한 풀이들 두고 이걸 복기했습니다. 

1. lambda x 쓸 때 함수 구성시에 다른 리스트 2개 엮어서 쓸 수 있었는데, 전 익숙치 않아서 나눠 했습니다.
함수식이 깔끔하게 떨어지는 거면 저렇게 하면 좋다는 것 알아갑니다.

2. 마지막 인덱스에서 indexError 날 것을 염려해 항상 인덱스를 하나 전으로 땡겨서 사용했는데 try...catch... 를 저렇게 활용할 수도 있군요. 

3. 왜 저런 아이디어를 생각하지 못 했을까.. 현재 인덱스값과 다음 인덱스값만 비교하고 싶기는 했는데 그럴 시에는 keep되는 count 가 늘어날 때는 어떻게 하나.. 해서 전 while문을 2개를 사용했습니다. 
그러나 이 풀이에서는 count가 늘 때마다 다음값을 현재값으로 업데이트하는 식으로 구현했습니다.

사실 이렇게 값을 같이 주면서 루트를 체크하는 아이디어는 서로소집합 알고리즘 사용하며 몇 번 이용했는데 왜 떠올리지 못했는지 정말 아쉬웠습니다. 다음에 비슷한 문제를 만나면 꼭 잘 사용할 수 있기를 바랍니다.