The best selling products this week
The weekly email lists the top products by units sold. Sales come in one row per transaction, so the same product appears many times.
- Add up the units per product name first.
- Order by units sold, largest first; products level on units go alphabetically.
- Return at most `howMany` names, or fewer if there are not that many products.
- Asking for zero or fewer returns nothing.
topSellers(sales: list<Sale>, howMany: int) → list<string>
C++ needs a compiler and Drill does not host one yet, so this page is the reference rather than an exercise: the problem, worked examples, and the solution in full. To type it out, the same problem runs in Python.
Where you start
std::vector<std::string> topSellers(std::vector<Sale> sales, int howMany) {
}
Worked examples
| Call | Result |
|---|---|
topSellers(std::vector<Sale>{Sale{std::string("mug"), 5}, Sale{std::string("pen"), 3}, Sale{std::string("mug"), 2}}, 2) | std::vector<std::string>{std::string("mug"), std::string("pen")} |
topSellers(std::vector<Sale>{Sale{std::string("zip"), 1}, Sale{std::string("ace"), 1}}, 2) | std::vector<std::string>{std::string("ace"), std::string("zip")} |
topSellers(std::vector<Sale>{Sale{std::string("mug"), 5}, Sale{std::string("pen"), 9}}, 1) | std::vector<std::string>{std::string("pen")} |
topSellers(std::vector<Sale>{Sale{std::string("mug"), 5}}, 0) | std::vector<std::string>{} |
Hint
Aggregate into a map, then sort the entries. The tie-break is what most solutions forget.
Reference solution in C++
std::vector<std::string> topSellers(std::vector<Sale> sales, int howMany) {
std::map<string, int> totals;
for (const auto& s : sales) totals[s.name] += s.qty;
std::vector<string> names;
for (const auto& kv : totals) names.push_back(kv.first);
std::sort(names.begin(), names.end(), [&](const string& a, const string& b) {
if (totals[a] != totals[b]) return totals[a] > totals[b];
return a < b;
});
if (howMany <= 0) return {};
if ((int) names.size() > howMany) names.resize(howMany);
return names;
}