📚 나의 풀이
이 문제는 부동 소수점 오차를 조심해야한다.
users의 형태 : users = [ 비율, 가격]
📃 문제 풀이 순서
1️⃣ 이모티콘 할인율 (10%, 20%, 30%, 40%)중에서 비율보다 낮은 할인율은 제거
function getDiscountRates(users) {
const minRate = Math.min(...users.map(([discountRate,_]) => discountRate))
return [40, 30, 20, 10].filter((rate) => rate >= minRate)
}
2️⃣ emoticons이 할인되어 책정될 수 있는 모든 가격 리스트를 만든다.
function generateDiscountCombinations(discount, emoticons) {
const combinations = [];
// 부동 소수 때문에 0.6을 바로 사용하지 않고 x*6/10을 사용
const count = {
40 : 6,
30 : 7,
20 : 8,
10 : 9
}
const backtrack = (discountIdx=0, currentCombo=[]) => {
if (currentCombo.length === emoticons.length) {
combinations.push([...currentCombo]);
return;
}
for (let i = discountIdx; i < discount.length; i++) {
currentCombo.push([
Math.floor((emoticons[currentCombo.length] * count[discount[i]])/10),
discount[i]
]);
backtrack(discountIdx, currentCombo);
currentCombo.pop();
}
}
backtrack();
return combinations;
}
입출력 예#1 을 기준으로 generateDiscountCombinations()를 호출하면 생성되는 배열은 아래와 같다.
[ 할인율이 적용된 이모티콘, 할인율]
3️⃣ 2번으로 만든 배열로 users 배열을 사용하여 이모티콘 플러스를 몇명이 가입했고 그 때 이모티콘 판매액이 얼마인지 나타내는 배열 생성
function getProfits(discountCombinations, users) {
const profits = []
discountCombinations.forEach((discountCombination, index) => {
const profit = {
"emoticonPlus" : 0,
"sales" : 0
}
users.forEach(([discountRate,limitPrice]) => {
const purchasedUser = discountCombination.filter(([_, desiredRate]) => desiredRate >= discountRate)
const totalPurchases = purchasedUser.reduce((acc,[pri,_]) => acc += pri, 0)
const isBuyEmoticonPlus = totalPurchases >= limitPrice
if(isBuyEmoticonPlus) {
profit.emoticonPlus+= 1
return
}
profit.sales += totalPurchases
})
profits.push(profit)
})
return profits.map(({emoticonPlus, sales}) => [emoticonPlus,sales])
}
입출력 예#1 을 기준으로 getProfits() 을 호출 하면 아래와 같다.
[[emoticonPlus, emoticonsSales]...]
4️⃣ 카카오톡 목표에 맞게 정렬한다.
profits.sort(([emoticonPlusA, emoticonsSalesA],[emoticonPlusB, emoticonsSalesB]) => {
if(emoticonPlusB === emoticonPlusA) return emoticonsSalesB - emoticonsSalesA
return emoticonPlusB - emoticonPlusA
})
이모티콘 플러스 서비스 가입자 수가 동일하면 이모티콘 판매액을 기준으로 내림차순 정렬하기
전체 코드
function solution(users, emoticons) {
// 40~10% 할인율중에서 users의 최소 비율보다 작은 할인율 제거
const discountRates = getDiscountRates(users)
// emoticons이 할인되어 책정될 수 있는 모든 가격 리스트
const discountCombinations = generateDiscountCombinations(discountRates, emoticons);
// [[emoticonPlus, emoticonsSales]...]
const profits = getProfits(discountCombinations, users)
// 이모티콘 플러스 서비스 가입자 수를 내림차순으로 정렬하고 서비스 가입자 수가 같으면 판매액을 내림차순으로 정렬
profits.sort(([emoticonPlusA, emoticonsSalesA],[emoticonPlusB, emoticonsSalesB]) => {
if(emoticonPlusB === emoticonPlusA) return emoticonsSalesB - emoticonsSalesA
return emoticonPlusB - emoticonPlusA
})
return profits[0]
}
function getDiscountRates(users) {
const minRate = Math.min(...users.map(([discountRate,_]) => discountRate))
return [40, 30, 20, 10].filter((rate) => rate >= minRate)
}
function generateDiscountCombinations(discount, emoticons) {
const combinations = [];
// 부동 소수 때문에 0.6을 바로 사용하지 않고 x*6/10을 사용
const count = {
40 : 6,
30 : 7,
20 : 8,
10 : 9
}
const backtrack = (discountIdx=0, currentCombo=[]) => {
if (currentCombo.length === emoticons.length) {
combinations.push([...currentCombo]);
return;
}
for (let i = discountIdx; i < discount.length; i++) {
currentCombo.push([
Math.floor((emoticons[currentCombo.length] * count[discount[i]])/10),
discount[i]
]);
backtrack(discountIdx, currentCombo);
currentCombo.pop();
}
}
backtrack();
return combinations;
}
function getProfits(discountCombinations, users) {
const profits = []
discountCombinations.forEach((discountCombination, index) => {
const profit = {
"emoticonPlus" : 0,
"sales" : 0
}
users.forEach(([discountRate,limitPrice]) => {
const purchasedUser = discountCombination.filter(([_, desiredRate]) => desiredRate >= discountRate)
const totalPurchases = purchasedUser.reduce((acc,[pri,_]) => acc += pri, 0)
const isBuyEmoticonPlus = totalPurchases >= limitPrice
if(isBuyEmoticonPlus) {
profit.emoticonPlus+= 1
return
}
profit.sales += totalPurchases
})
profits.push(profit)
})
return profits.map(({emoticonPlus, sales}) => [emoticonPlus,sales])
}
'알고리즘 > 프로그래머스 - JS' 카테고리의 다른 글
[프로그래머스 - JS] level.1 달리기 경주 ❗️ (0) | 2023.06.17 |
---|---|
[프로그래머스-JS] level.2 택배 배달과 수거하기 ⭐️⭐️ (0) | 2023.06.16 |
[프로그래머스-JS] level.2 거리두기 확인하기 (0) | 2023.06.10 |
[프로그래머스] level.1 공원 산책 ⭐️ (0) | 2023.06.08 |
[프로그래머스-JS] level.1 신고 결과 받기 📌 (1) | 2023.06.07 |