본문 바로가기

코테연습문제

[Programmers/Python] 이모티콘 할인행사

프로그래머스 < 이모티콘 할인행사 >

 

문제 간단히 생각하기

1. 할인율은 10%, 20%, 30%, 40% 이고,

 

2. 사용자는 각각 '최소 할인율'과 '최대 구매 가능 금액' 을 가지고 있습니다.

 

3. 사용자는 이모티콘를 구매하거나, 이모티콘 플러스에 가입할 수 있는데,

 

4. 3번에 대한 기준은, '최소 할인율' 이상의 할인율을 적용시켜 구매한 이모티콘의 가격이

4-1. '최대 구매 가능 금액' 미만인 경우, 이모티콘 구매하고,

4-2. '최대 구매 가능 금액' 이상인 경우, 이모티콘 플러스 가입

 

5. 이모티콘 플러스 가입자가 최대인 경우 중, 판매액을 최대로 하는 경우의 이모티콘플러스 가입자수와 판매액을 출력

 

 

해야할 일

1. 각 이모티콘에 대해 적용할 할인율의 경우의 수를 구합니다.

2. 각 할인율을 적용시킨 금액을 모두 더해서 사용자가 정한 '최대 구매 가능 금액'과 비교해,

3. 이모티콘 플러스 가입 여부를 판단합니다.

4. 구했던 이모티콘 플러스 최대 가입자수와 판매액을 구해 출력합니다.

 

def solution(users, emoticons):
    dcRate = [10, 20, 30, 40]
    answer = [0, 0]
    discount = []
    
    # 각 이모티콘 별 적용시킬 할인율 조합 경우의 수
    # [10,10], [10,20], [10,30], [10,40], [20,10], [20,20], ... ,[40,40]
    # discount = list(itertools.product(dcRate, repeat=len(emoticons)))
    def dc(rate, d):
        if d == len(rate):
            discount.append(rate[:])
            return
        else:
            for i in dcRate:
                rate[d] += i
                dc(rate, d+1)
                rate[d] -= i
                
    dc([0]*len(emoticons), 0)
    
    # 각 사용자 별 임티를 구입할 때 금액 합계를 구하고,
    # 최대 구매 비용을 초과하면 이모티콘 플러스 가입
    for dc in discount:
        emPlus = 0  # 이모티콘 플러스 가입자 수
        emBuy = 0  # 이모티콘 구매 금액
        for user in users:
            total = 0 # 사용자별로 total을 따로 구해줘야하므로, 새로운 사용자를 만나면서 초기화
            for i in range(len(emoticons)):
            	# 각 사용자의 기준 할인율 이상이면 이모티콘을 구매
                if user[0] <= dc[i]:
                    total += emoticons[i] * ((100 - dc[i]) / 100)
                
                # 이모티콘 구매 비용이 일정 가격 이상이 되면, 이모티콘 구매를 취소하고
                if total >= user[1]:
                    break
            # 이모티콘 플러스 서비스에 가입
            if total >= user[1]:
                emPlus += 1
                total = 0  # 이모티콘 구매를 취소했으므로, 가격을 0으로 설정
            emBuy += total  # 한 사용자에 대해 이모티콘을 구매한 총 합을 emBuy에 저장
            
        # 이모티콘 플러스 가입자를 최대로 늘리는 것이 최우선의 목표이므로,
        # 이모티콘 플러스 가입자의 수를 이전까지의 최대 가입자 수와 비교해서, 더 크다면 갱신시켜줌
        if emPlus >= answer[0]:
            # 만약 최대의 이모티콘 플러스 가입자 수가 같다면,
            # 두 번째 목표인 '최대 판매액'을 위해 emBuy의 최대 금액을 answer[1]에 갱신시켜줌
            if emPlus == answer[0]:
                answer[1] = max(answer[1], emBuy)
            else:
                answer[0], answer[1] = emPlus, emBuy
    
    return answer

풀이과정

1. 각 이모티콘에 대해 적용할 할인율의 경우의 수를 구하기 위해 dc 함수를 만듦

※ def dc(rate, d)를 사용하지 않고,

import itertools를 해주고 주석처리해둔 " discount = list(itertools.product(dcRate, repeat=len(emoticons))) "를 사용해도 됩니다.

'중복순열'을 사용해 각 이모티콘에 대해 적용할 할인율의 모든 경우의 수를 구할 수 있습니다.

 

2. 각 할인율을 적용시킨 금액을 모두 더해서 사용자가 정한 '최대 구매 가능 금액'과 비교

2-1. '최대 구매 가능 금액' 이상: 즉시 break를 하고, 이모티콘 플러스 가입자 수를 +1한 뒤, 구매 금액은 0으로 초기화 시켜 이모티콘의 개별 구매를 취소했다고 표현

2-2. '최대 구매 가능 금액' 미만: 이모티콘 판매액(emBuy)에 금액을 더해줌

 

3. 2에서 구한 이모티콘 플러스 가입자 수와 이전까지의 최대 이모티콘 플러스 가입자수를 비교해 2에서 구한 이모티콘 플러스 가입자 수가 더 크거나 같을 때만 갱신

3-1. 더 클 경우: 2에서 구한 이모티콘 플러스 가입자 수와 판매액으로 answer을 갱신

→ 판매액은 신경쓰지 않음(이모티콘 플러스 가입자 최대가 우선목표이기 때문)

3-2. 같을 경우: 이전까지의 최대 판매액과 비교해, 더 큰 금액으로 answer[1]을 갱신

 

4. 모든 할인율 경우의 수를 실행시킨 뒤에 구해진 answer을 출력