fork download
  1. #include <iostream>
  2. #include <sstream>
  3. #include <memory>
  4. #include <map>
  5. #include <vector>
  6.  
  7. struct Item
  8. {
  9. public:
  10. std::string id;
  11. std::string name;
  12. double price;
  13.  
  14. Item(const std::string& id, const std::string& name, double price) : id(id), name(name), price(price) {}
  15.  
  16. //just to be able to put it in a map
  17. bool operator<(const Item& b) const
  18. {
  19. return price < b.price;
  20. }
  21. friend std::ostream& operator<<(std::ostream& out, const Item& item);
  22. };
  23.  
  24. std::ostream& operator<<(std::ostream& out, const Item& item)
  25. {
  26. return out << '[' << item.id << "] " << item.name << " (" << item.price << " $)";
  27. }
  28.  
  29. //indexing the tours by their respective IDs
  30. const std::map<std::string, Item> tours {
  31. {"OH", Item("OH", "Opera House Tour", 300.0)},
  32. {"BC", Item("BC", "Syndney Bridge Climb", 110.0)},
  33. {"SK", Item("SK", "Syndney Sky Tower", 30.0)},
  34. };
  35.  
  36. class Rule
  37. {
  38. public:
  39. virtual std::map<Item, int> applyDiscount(std::map<Item, int> items) = 0;
  40. };
  41.  
  42. class FreeSkyTourRule : public Rule
  43. {
  44. std::map<Item, int> applyDiscount(std::map<Item, int> items)
  45. {
  46. auto oh = items.find(tours.at("OH"));
  47. if(oh == items.end())
  48. return items;
  49. auto sk = items.find(tours.at("SK"));
  50. if(sk == items.end())
  51. return items;
  52. Item discount("DC", "Free Sky Discount", -sk->first.price);
  53. items[discount] = sk->second > oh->second ? oh->second : sk->second;
  54. return items;
  55. }
  56. };
  57.  
  58. class ThreeForTwoRule : public Rule
  59. {
  60. std::map<Item, int> applyDiscount(std::map<Item, int> items)
  61. {
  62. auto oh = items.find(tours.at("OH"));
  63. if(oh == items.end())
  64. return items;
  65. int quantity = oh->second;
  66. Item discount("DC", "Opera House Discount", -oh->first.price);
  67. if(quantity > 2)
  68. items[discount] = oh->second / 3;
  69. return items;
  70. }
  71. };
  72.  
  73. class BridgeClimbDiscountRule : public Rule
  74. {
  75. std::map<Item, int> applyDiscount(std::map<Item, int> items)
  76. {
  77. auto bc = items.find(tours.at("BC"));
  78. if(bc == items.end())
  79. return items;
  80. int quantity = bc->second;
  81. if(quantity > 4)
  82. {
  83. Item discount("DC", "Bridge Climb Discount", -20.0);
  84. items[discount] = quantity;
  85. }
  86. return items;
  87. }
  88. };
  89.  
  90. class ShoppingCart
  91. {
  92. private:
  93. std::map<Item, int> items;
  94. std::vector<std::unique_ptr<Rule>> rules;
  95.  
  96. public:
  97. void addItem(Item item)
  98. {
  99. items[item]++;
  100. }
  101.  
  102. void addRule(std::unique_ptr<Rule> rule)
  103. {
  104. rules.push_back(std::move(rule));
  105. }
  106.  
  107. std::map<Item, int> getBill() const
  108. {
  109. std::map<Item, int> bill = items;
  110. for(auto& rule: rules)
  111. bill = rule->applyDiscount(bill);
  112. return bill;
  113. }
  114.  
  115. double total(const std::map<Item, int>& bill) const
  116. {
  117. double sum = 0;
  118. for(auto& kv: bill)
  119. sum += kv.first.price * kv.second;
  120. return sum;
  121. }
  122.  
  123. double total() const
  124. {
  125. return total(getBill());
  126. }
  127. };
  128.  
  129. int main()
  130. {
  131. std::string line;
  132. while(getline(std::cin, line))
  133. {
  134. std::string entry;
  135. std::stringstream ss(line);
  136. ShoppingCart cart;
  137. while(ss >> entry)
  138. {
  139. cart.addItem(tours.at(entry));
  140. }
  141. cart.addRule(std::unique_ptr<Rule>(new BridgeClimbDiscountRule));
  142. cart.addRule(std::unique_ptr<Rule>(new ThreeForTwoRule));
  143. cart.addRule(std::unique_ptr<Rule>(new FreeSkyTourRule));
  144. std::cout << line << std::endl;
  145. auto bill = cart.getBill();
  146. for(auto& kv: bill)
  147. std::cout << "\tx" << kv.second << " : " << kv.first << std::endl;
  148. std::cout << "\tTotal in $ : " << cart.total(bill) << std::endl;
  149. std::cout << std::endl;
  150. }
  151. return 0;
  152. }
Success #stdin #stdout 0s 15256KB
stdin
OH OH OH BC
OH SK
BC BC BC BC BC OH
OH OH OH BC SK
OH BC BC SK SK
BC BC BC BC BC BC OH OH
SK SK BC
OH OH OH SK SK SK
stdout
OH OH OH BC
	x1 : [DC] Opera House Discount (-300 $)
	x1 : [BC] Syndney Bridge Climb (110 $)
	x3 : [OH] Opera House Tour (300 $)
	Total in $ : 710

OH SK
	x1 : [DC] Free Sky Discount (-30 $)
	x1 : [SK] Syndney Sky Tower (30 $)
	x1 : [OH] Opera House Tour (300 $)
	Total in $ : 300

BC BC BC BC BC OH
	x5 : [DC] Bridge Climb Discount (-20 $)
	x5 : [BC] Syndney Bridge Climb (110 $)
	x1 : [OH] Opera House Tour (300 $)
	Total in $ : 750

OH OH OH BC SK
	x1 : [DC] Opera House Discount (-300 $)
	x1 : [DC] Free Sky Discount (-30 $)
	x1 : [SK] Syndney Sky Tower (30 $)
	x1 : [BC] Syndney Bridge Climb (110 $)
	x3 : [OH] Opera House Tour (300 $)
	Total in $ : 710

OH BC BC SK SK
	x1 : [DC] Free Sky Discount (-30 $)
	x2 : [SK] Syndney Sky Tower (30 $)
	x2 : [BC] Syndney Bridge Climb (110 $)
	x1 : [OH] Opera House Tour (300 $)
	Total in $ : 550

BC BC BC BC BC BC OH OH
	x6 : [DC] Bridge Climb Discount (-20 $)
	x6 : [BC] Syndney Bridge Climb (110 $)
	x2 : [OH] Opera House Tour (300 $)
	Total in $ : 1140

SK SK BC
	x2 : [SK] Syndney Sky Tower (30 $)
	x1 : [BC] Syndney Bridge Climb (110 $)
	Total in $ : 170

OH OH OH SK SK SK
	x1 : [DC] Opera House Discount (-300 $)
	x3 : [DC] Free Sky Discount (-30 $)
	x3 : [SK] Syndney Sky Tower (30 $)
	x3 : [OH] Opera House Tour (300 $)
	Total in $ : 600