Algorithm

[프로그래머스/JavaScript] Lv.2 이모티콘 할인행사

cob 2023. 1. 12. 08:18

 

 

 

 

프로그래머스

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

programmers.co.kr

 

 

 


1. 문제 설명

카카오톡에서는 이모티콘을 무제한으로 사용할 수 있는 이모티콘 플러스 서비스 가입자 수를 늘리려고 합니다.
이를 위해 카카오톡에서는 이모티콘 할인 행사를 하는데, 목표는 다음과 같습니다.

  1. 이모티콘 플러스 서비스 가입자를 최대한 늘리는 것.
  2. 이모티콘 판매액을 최대한 늘리는 것.

1번 목표가 우선이며, 2번 목표가 그 다음입니다.

이모티콘 할인 행사는 다음과 같은 방식으로 진행됩니다.

  • n명의 카카오톡 사용자들에게 이모티콘 m개를 할인하여 판매합니다.
  • 이모티콘마다 할인율은 다를 수 있으며, 할인율은 10%, 20%, 30%, 40% 중 하나로 설정됩니다.

카카오톡 사용자들은 다음과 같은 기준을 따라 이모티콘을 사거나, 이모티콘 플러스 서비스에 가입합니다.

  • 각 사용자들은 자신의 기준에 따라 일정 비율 이상 할인하는 이모티콘을 모두 구매합니다.
  • 각 사용자들은 자신의 기준에 따라 이모티콘 구매 비용의 합이 일정 가격 이상이 된다면, 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.

제한사항

 

 


2. 입출력 예

입출력 예
입출력 예 2

 

 

 


3. 문제 풀이

깊이 탐색(DFS)을 통해 이모티콘 할인율에 대한 가짓수를 구하고, 그 중 조건에 맞는 최댓값을 구한다.

 

function solution(users, emoticons) {
    // 1) 최대 값 담을 변수 선언
    const answer = [0, 0];
    
    // 2) 할인율 변순 선언
    const discount = [10, 20, 30, 40];
        
    /* 
        3) 이모티콘마다 할인율을 적용 가능한 가짓수를 담는다. 
        ex) 이모티콘 2개 -> 4 * 4 = 16, 이모티콘 3개 -> 4 * 4 * 4 = 64 가짓수가 나온다.
    */
    const arr = [];
    
    // 4) 깊이 탐색을 통해 가능한 가짓수를 탐색한다. result : 이모티콘별 할인율 적용 값
    function dfs(emoticons, result) {
        
        // 5) 이모티콘이 없으면 탐색 종료
        if (emoticons.length < 1) {
            
            // 6) arr 배열에 탐색한 결괏값을 추가한다.
            arr.push(result);
            return;
        }
       
        // 7) 할인율 개수만큼 반복한다. 
        for (let i=0; i<discount.length; i++) {
            
            // 8) 이모티콘 개수를 하나씩 줄이고, 줄였던 이모티콘의 할인율과 원가를 result에 담는다.
            dfs(emoticons.slice(1), [...result, [discount[i], emoticons[0]]]);
        }
    }
    
    // 9) 최초 dfs 함수 실행
    dfs(emoticons, []);
    
    // 10) 할인가 계산 함수
    const disAmt = (dis, price) => (100-dis) / 100 * price;
    
    // 11) 모든 가짓수만큼 실행한다.
    arr.forEach(disArr => {
        
        // 12) 가짓수마다 서비스 가입 수와 매출액을 구한다. [가입자 수, 총 매출액]
        const accrue = [0, 0]
        
        // 13) 사용자 수만큼 반복한다.
        users.forEach(([per, price]) => {
            
            // 14) 매출액 변수 선언
            let sum = 0;
            
            // 15) 가짓수에 담긴 이모티콘의 개수만큼 실행한다.
            disArr.forEach(([dis, cost]) => {
                
                // 16) 사용자의 할인가 이상만 매출액을 구한다.
                if(dis >= per) {
                    
                    // 17) 총 매출액을 구한다.
                    sum += disAmt(dis, cost);
                }
            });
            
            // 18) 사용자의 마지노선 가격보다 매출액이 높으면, 그냥 서비스를 가입한다.
            if(sum >= price) {
                
                // 19) 서비스 증가
                accrue[0] += 1;  
            } else {
                
                // 20) 높지 않다면 매출액을 증가시킨다.
                accrue[1] += sum;
            }
        });
        
        // 21) 최댓값을 비교한다. 우선순위 : 서비스 가입자 수 > 매출액 
        if(answer[0] < accrue[0]) {
            
            // 22) 가입자 수가 더 많으면 accrue 값으로 최댓값 변경
            answer[0] = accrue[0];
            answer[1] = accrue[1];
        } else if(answer[0] === accrue[0]) {
            
            // 23) 동일할 경우
            if(answer[1] < accrue[1]) {
                
                // 24) 매출액으로 최댓값을 비교한다.
                answer[1] = accrue[1];
            }
        }
        
    }); 
    
    // 25) 최댓값을 return 한다.
    return answer;
}

 

 

 

반응형