2024년 4월 17일 수요일

2023 KAKAO BLIND RECRUITMENT 이모티콘 할인행사

문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/150368

파이썬 소스: https://bit.ly/3TXgolX

 

이모티콘 플러스 서비스에 가입하는 것이 우선이고, 그 다음 조건이 이모티콘을 적게 할인을 해서, 최대한 비싸게 파는 것입니다. 각 사용자 별로 구매하는 할인율이 다르기 때문에, 모든 경우의 수를 다 계산해 보는 방법 밖에 없습니다.

이 문제의 답을 구하기 위해서는, 모든 users에게, 모든 이모티콘의 할인율의 가능성을 모두 적용해서 계산해 봐야 문제의 답을 구할 수 있습니다.

 문제에서는 이모티콘의 할인율을 아래와 같이 설명하고 있습니다.

이모티콘마다 할인율은 다를 수 있으며, 할인율은 10%, 20%, 30%, 40% 중 하나로 설정됩니다.

 

이모티콘의 할인율은 4가지입니다. 10% 20% 30% 40%

첫번째 이모티콘이 10% 할인율일 때, 두번째 이모티콘의 할인율도 10%일 수 있습니다. 위의 문제 설명을 보면, 조끔 헷갈려서, 이모티콘의 할인율이 모두 달라야 한다고 생각할 수 있지만, 아닙니다. 정확하게 ‘다를 수 있으며’라고 했기 때문에, 같을 수도 있는 것입니다.

 조금 다른 관점에서 보면, 이모티콘의 할인율이 모두 달라야 한다면, 이모티콘의 종류는 4개를 넘을 수 없습니다. 하지만 문제에서는 이모티콘의 종류가 7개 까지라고 설명하고 있기 때문에, 이모티콘의 할인율이 같을 수도, 다를 수도 있다고 보는 것이 문제를 올바르게 이해한 것입니다.

입출력 예 첫번재 처럼, 이모티콘의 개수가 2개라고 한다면 가능한 이모티콘의 할인율은 아래와 같습니다. 튜플의 인덱스 0번이 첫번째 이모티콘의 할인율이고, 인덱스 1번이 두번째 이모티콘의 할인율입니다. 총 16가지입니다.

(10, 10), (10, 20), (10, 30), (10, 40),

(20, 10), (20, 20), (20, 30), (20, 40),

(30, 10), (30, 20), (30, 30), (30, 40),

(40, 10), (40, 20), (40, 30), (40, 40)

 

위와 같은 경우를 중복순열이라고 하구요, 파이썬에서는 product()함수를 사용해서 중복순열을 구할 수 있습니다. 중복순열의 한 원소의 길이는 이모티콘의 종류의 수입니다.

def solution(users: List[List[int]], emoticons: List[List[int]]):
    discounts =
list(product([10, 20, 30, 40], repeat=len(emoticons)))

 

이제 모든 가능한 이모티콘의 할인율을 구했으니, 각 할인율 마다, user가 이모티콘 플러스 서비스에 가입하는지, 이모티콘을 할인된 가격에 구매하는지 계산해볼 차례입니다.

for discount in discounts:
    local_subscriber =
0
   
local_sell = 0

   
for user in users:
        local_user_subscriber =
False
       
local_user_sell = 0
       
user_dis, user_sell_limit = user

튜플 discount가 가리키는 각 이모티콘의 핳인율을 각 user에게

튜플 discount에 따른 이모티콘 플러스 서비스 가입자수 local_subscriber

튜플 discount에 따른 이모티콘 구입의 총함 local_sell

해당 user가 이모티콘 플러스 서비스에 가입하는지 여부 local_user_subscriber

해당 user가 구매한 이모티콘의 가격 local_user_sell

해당 user는 이 할인율 이하이면 이모티콘을 구입하는 할인윻 user_dis

해당 user가 구입가능한 최대 이모티콘 가격의 합 user_sell_limit

이제 각 user가 어떻게 행동하는지, 튜플 discount에서 제시된 할인율에 따라서, 알아볼 차례입니다.

for idx in range(len(emoticons)):
    emo_dis, emo_price = discount[idx], emoticons[idx]
   
if user_dis <= emo_dis:
        local_user_sell += (emo_price * (
100 - emo_dis) // 100)

   
if local_user_sell >= user_sell_limit:
        local_user_subscriber =
True
        break

이모티콘의 할인율이 원하는 할인율의 이하라면, 할인된 가격으로 이모티콘을 구매하고, 구매한 가격을 local_user_sell 에 저장합니다.

이모티콘을 구해한 가격의 합이 user_sell_limit의 이상이면, 해당 user는 이모티콘을 구매하지 않고, 이모토킨 플러스 서비스에 가입합니다. 이모티콘 플러스 서비스에 가입하면, 더 이상 이모티콘을 구매하지 않기 때문에, break로 루프를 나오게 됩니다.

if local_user_subscriber:
    local_subscriber +=
1
else:
    local_sell += local_user_sell

이모티콘 플러스 서비스에 가입했다면, local_subscriber를 1증가시켜줍니다. 아니라면, 구매한 이모티콘의 가격의 합을 local_sell에 더해줍니다.

 

한번 discount에 대한 루프가 끝날 때 마다, 모든 유저들이 이모티콘 플러스 서비스에 가입하는지, 얼마나 이모티콘을 구매하는대 사용했는지 알 수 있습니다.

answer.append([local_subscriber, local_sell])
answer.sort(
reverse=True)
answer = [answer[
0]]

리스트 answer에 이모티콘 플러스 가입자 수와, 이모티콘 판매가격의 합을 appen()메서드로 넣어 줍니다. 첫 루프라면, answer에 1개의 원소만 들어 있기 때문에, sort()하는 의미가 없지만, 두번재 루프 부터는 2가의 원소중에 sort(reverse=True)로 큰 값이 앞에 오게 됩니다.

따라서 answer[0]만 다시 answer에 넣어 주면, 문제에서 원하는 최대값이 answer[0]에 들어 있게 됩니다.

 

궁금한 내용은 댓글, 이메일(coding.data.pul@gmail.com)로 보내주세요.

코데풀 유튜브 구독 부탁드립니다.

https://www.youtube.com/@codapul

 

전체 코드는 아래에 있습니다.

from typing import List
from itertools import product


def solution(users: List[List[int]], emoticons: List[List[int]]):
    discounts =
list(product([10, 20, 30, 40], repeat=len(emoticons)))
    answer = []

   
for discount in discounts:
        local_subscriber =
0
       
local_sell = 0

       
for user in users:
            local_user_subscriber =
False
           
local_user_sell = 0
           
user_dis, user_sell_limit = user

           
for idx in range(len(emoticons)):
                emo_dis, emo_price = discount[idx], emoticons[idx]
               
if user_dis <= emo_dis:
                    local_user_sell += (emo_price * (
100 - emo_dis) // 100)

               
if local_user_sell >= user_sell_limit:
                    local_user_subscriber =
True
                    break

            if
local_user_subscriber:
                local_subscriber +=
1
           
else:
                local_sell += local_user_sell

        answer.append([local_subscriber, local_sell])
        answer.sort(
reverse=True)
        answer = [answer[
0]]

   
return answer[0]

 

 

댓글 없음:

댓글 쓰기