| 4 | 4 | // |
| 5 | 5 | |
| 6 | 6 | export const cost = (books) => { |
| 7 | | throw new Error('Remove this line and implement the function'); |
| 7 | // Edge Case: Empty basket |
| 8 | if (books.length === 0) { |
| 9 | return 0; |
| 10 | } |
| 11 | |
| 12 | // Count how many of each book we have |
| 13 | const counts = Array(5).fill(0); |
| 14 | for (const book of books) { |
| 15 | counts[book - 1]++; |
| 16 | } |
| 17 | |
| 18 | // Edge Case: All same books (no discount possible) |
| 19 | const uniqueBooks = counts.filter(count => count > 0).length; |
| 20 | if (uniqueBooks === 1) { |
| 21 | return books.length * 800; // $8.00 = 800 cents |
| 22 | } |
| 23 | |
| 24 | // Sort counts in descending order to simplify calculation |
| 25 | counts.sort((a, b) => b - a); |
| 26 | |
| 27 | // Try all possible groupings and find the minimum cost |
| 28 | return calculateMinCost(counts); |
| 8 | 29 | }; |
| 30 | |
| 31 | // Helper function to calculate minimum cost using recursive approach |
| 32 | function calculateMinCost(counts) { |
| 33 | // Remove empty counts |
| 34 | counts = counts.filter(count => count > 0); |
| 35 | |
| 36 | // Edge Case: No books left |
| 37 | if (counts.length === 0) { |
| 38 | return 0; |
| 39 | } |
| 40 | |
| 41 | // Edge Case: Only one copy of each book type left |
| 42 | if (counts.every(count => count === 1)) { |
| 43 | const numBooks = counts.length; |
| 44 | const discount = getDiscount(numBooks); |
| 45 | return numBooks * 800 * (1 - discount) + calculateMinCost([]); |
| 46 | } |
| 47 | |
| 48 | let minCost = Infinity; |
| 49 | |
| 50 | // Try creating a group of size 1 to 5 |
| 51 | for (let groupSize = 1; groupSize <= Math.min(5, counts.length); groupSize++) { |
| 52 | // Check if we can form a group of this size |
| 53 | if (counts.length >= groupSize) { |
| 54 | // Create a new counts array with one book of each of the first groupSize types removed |
| 55 | const newCounts = [...counts]; |
| 56 | for (let i = 0; i < groupSize; i++) { |
| 57 | newCounts[i]--; |
| 58 | } |
| 59 | |
| 60 | // Calculate cost for this grouping |
| 61 | const discount = getDiscount(groupSize); |
| 62 | const groupCost = groupSize * 800 * (1 - discount); |
| 63 | const remainingCost = calculateMinCost(newCounts); |
| 64 | const totalCost = groupCost + remainingCost; |
| 65 | |
| 66 | minCost = Math.min(minCost, totalCost); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | return minCost === Infinity ? 0 : minCost; |
| 71 | } |
| 72 | |
| 73 | // Helper function to get discount based on group size |
| 74 | function getDiscount(groupSize) { |
| 75 | switch (groupSize) { |
| 76 | case 2: return 0.05; |
| 77 | case 3: return 0.10; |
| 78 | case 4: return 0.20; |
| 79 | case 5: return 0.25; |
| 80 | default: return 0; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | // Handled Edge Cases: Empty basket, All same books, No books left, Only one copy of each book type |