본문 바로가기
알고리즘

[프로그래머스] Kakao 2023 blind 이모티콘 할인행사 [파이썬 코드 + 어떤 논리를 전개할 수 있을까?]

by itstime0809 2023. 10. 26.
728x90

구현,  정렬

https://school.programmers.co.kr/learn/courses/30/lessons/150368

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

코드

from itertools import product
def solution(users, emoticons):
    answer = []
        
    # 할인율
    sales_list = [10, 20, 30, 40]
    
    # 할인율에 대해서 이모티콘의 개수만큼 할인율들을 뽑아보자
    for i in product(sales_list, repeat=len(emoticons)):
        sales = i
        total_money = 0
        emoticon_plus = 0
        for user in users:
            # 기준율, 기준 money
            stand_sales, stand_money = user[0], user[1]
            
            user_money = 0
            for j in range(len(sales)):
                # 기준율 이상이라면
                if stand_sales <= sales[j]:
                    user_money += emoticons[j] * ((100 - sales[j]) / 100)
      
            if user_money >= stand_money:
                emoticon_plus += 1
            else:
                total_money += user_money
                continue
            
        answer.append((emoticon_plus, total_money))
    answer_list = sorted(answer, key=lambda x : (-x[0], -x[1]))
    return list(map(int, answer_list[0]))

 

설명

 카카오 문제 중에서 그나마 지금 내 실력에서 풀어볼 수 있었던 문제 같아 글쓰기를 시작한다. 이번 문제는 Kakao 2023 blind 코딩 테스트 문제로 나온 문제 같다. 문제를 읽어보면 알 수 있듯이 분명한 목적의 우선순위가 존재한다. 그 우선순위는 아래와 같다.

 

 

1. 이모티콘 플러스 가입자 수 가 많아야 한다.

2. 이모티콘을 산 금액이 많아야 한다.

 

 

 목적은 분명하다. 이모티콘 플러스 가입자 수가 많은 게 첫 번째 목표이고, 두 번째는 이모티콘을 산 금액이 많아야 한다는 게 두 번째 목표다. 그리고 조건에서 각각의 이모티콘에 할인율을 적용할 수 있다고 한다. 네 가지 할인율이 적용되며 10, 20, 30, 40(%)로 랜덤 하게 지정된다고 한다. 또 유저가 구입하게 될 이모티콘은 자신이 가진 기준율 즉 어떠한 할인율 이상인 이모티콘만 사겠다는 것을 의미한다. 반대로 말하면 어떠한 할인율 미만인 것들은 사지 않는다. 마지막으로 기준에 맞춰 구입한 이모티콘의 총금액 여기서 의미하는 총금액이란 유저 한 명이 구입하게 되는 이모티콘의 총금액을 의미한다. 따라서 유저가 구입한 이모티콘의 총금액이 자신이 설정한 금액 이상이라면 그 유저는 이모티콘 플러스에 가입해야 한다. 만약 자신이 설정한 금액보다 적은 금액이라면 이모티콘 플러스에 가입하지 않는다.

 

 로직 구현을 위한 핵심 사항들은 위에 대략적으로 적은 것 같다. 이 문제를 풀어보면서 중요한 것은 사실 가장 맨 뒤에 있는 sorted() 부분이지만 논리를 전개함에 있어 product도 한 역할을 한다고 보여진다. 그중 왜 product를 사용했는지 먼저 설명해 보려고 한다. product는 중복순열이다. 중복순열이라고 하는 것은 '순열의 개념에서는 중복을 허락하지 않는다.' 중복 순열은 그러면 중복을 포함하는 순열이라는 의미가 된다. 또한 순서를 고려한다는 것이 중요하다고 생각했다. 할인율은 각각의 이모티콘에 지정되기 때문에 10%, 20% 와 20%, 10%는 다른 할인율을 보이게 되기 때문이다. 만약 이것을 조합으로 생각하거나 순열로 생각한다면 중복을 고려하지 않는 케이스 즉 40%, 40% 와 같이 중복된 할인율을 생각하지 않게 되는 것이다. 따라서 중복순열은 이러한 케이스를 모두 해결해 줄 수 있기 때문에 product를 사용해서 중복된 할인율까지도 고려하고, 순서도 고려하여 각 이모티콘마다 할인율을 다르게 적용한 케이스까지 모두 해결했다.

 

 구하고 싶은 목적의 우선순위는 플러스 가입자 수가 많아야 하는게 우선이지만, 어떤 케이스에서 얼마나 많은 플러스 가입자 수가 나올지는 단번에 알아내기 힘들다. 그렇기 때문에 중복순열로 구한 각기 다른 할인율을 적용해 가며 유저들의 금액을 구해보고, 플러스 가입자수를 올리거나 총금액에 반영하는 식으로 구현이 가능하다. 왜냐하면 플러스에 가입하는 유저는 구입한 모든 이모티콘을 취소하기 때문에 결국 이모티콘을 구매하지 않는 것이며, 모든 금액을 구하게 되는 부분에 누적을 하지 않더라도 다음 유저의 금액을 구하기 위해 자동 초기화 되며 결국 이모티콘 플러스 가입자수만 증가시켜 주면 되기 때문이다. 만약 이모티콘 플러스에 가입하지 않는 유저라면 결국 그 이모티콘을 모두 사는 유저이므로 그 유저가 산 모든 이모티콘의 금액만큼을 총금액에 누적시켜 주면 된다.

 

 이후 목적에 맞게 답을 구하기 위해서는 몇가지 생각을 좀 해야 하는데 우선순위에 대해서 생각을 해야 한다고 보고 있다. 우선순위는 말 그대로 어떤 것이 어떤 것 보다 더 우선한 권리를 가진다. 혹은 더 우선한 순서를 갖는다 정도로 이해해 볼 수 있을 것 같다. 그럼 플러스 가입자 수가 우선적인 순서를 가져야 하기 때문에 많은 이모티콘 플러스 가입자 수를 확보하고 싶은 문제의 목적상. 플러스 가입자 수가 가장 많은 순서를 우선적으로 정렬을 하고, 만약에 플러스 가입자 수가 동일한 경우가 존재할 수 있다. 그럴 때는 금액이 많은 순서가 그다음 목적을 지니기 때문에 금액이 큰 순서대로 정렬을 하게 된다면 두 가지 우선순위에 대한 목적에 부합하게 된다.

 

 sorted()를 사용해서 lambda 단일 함수로 정렬을 시킬때 어떤 기준으로 정렬이 되는지를 앞에서 연습해 보았기 때문에 풀 수 있었던 문제라고 생각한다. 만약 마지막에도 우선순위를 고려하지 않는다면 플러스 가입자 수는 많지만 금액이 더 적은 케이스를 선택할 수 있기 때문에 정답으로 처리되지 않는다. 따라서 위 문제는 문제의 조건대로 구현하고, sorted()에 정렬 방식을 사용하여 풀 수 있는 문제다.