AlgoMaster Logo
AlgoMasterDesign Discount Calculatormedium

Design Discount Calculator

medium

Design a discount calculator that supports three policies: Percentage, Flat, and Buy One Get One Free. Every discount can calculate a new price, provide a label, and describe its effect. The calculation and label vary by policy, while the description format stays the same.

The provided PricingEngine class supports these operations:

  • PricingEngine() creates an engine holding no discounts.
  • int addPercentage(int percent) adds a discount taking percent off, and returns the index it was stored at. Its label is "<percent>% off".
  • int addFlat(double amount) adds a discount taking a fixed amount off, and returns the index. Its label is "$<amount> off" with the amount to two decimals.
  • int addBuyOneGetOne() adds a discount halving the price, and returns the index. Its label is "Buy 1 Get 1 Free".
  • double priceAfter(int index, double price) returns the price after the discount at index is applied:
    • Percentage gives price * (1 - percent / 100).
    • Flat gives price - amount, and never less than 0.
    • Buy one get one free gives price / 2.
  • String label(int index) returns the label of the discount at index.
  • String describe(int index, double price) returns "<label>: $<price> -> $<newPrice>", both amounts to two decimals and with no thousand separators.
  • int discountCount() returns how many discounts are stored.

Discounts are stored in insertion order starting at index 0, and the same kind can be added more than once with different settings. Adding a fourth kind of discount later must not require changing describe, priceAfter or discountCount.

Your task is to implement the abstract Discount base class and the concrete PercentageDiscount, FlatDiscount, and BuyOneGetOneFree subclasses. Do not modify the provided PricingEngine class. Keep the shared describe behavior on the base class, and place each calculation and label inside the corresponding subclass.

Example 1:

Input:

Output:

Explanation: The 20% discount is stored at index 0 and changes 100 to 80. The flat discount is stored at index 1 and subtracts 15, leaving 85. Each policy supplies its own label and calculation while reusing the same description format.

Example 2:

Input:

Output:

Explanation: Buy One Get One Free halves the price, so 79.98 becomes 39.99. It is the only discount stored in the engine, so the count is 1.

Constraints:
  • 0 <= percent <= 100
  • 0 <= amount <= 10^4
  • 0 <= price <= 10^4
  • index always refers to a discount that has been added.
  • At most 100 calls will be made across all methods.

How the design is graded

needs 7/10 to pass
  • Polymorphic pricing

    Full marks when a shared discount type declares the price calculation and each kind implements it, so priceAfter and describe delegate without knowing which kind they hold. Lose points heavily when the engine stores a discount-kind tag and branches on it to work out the new price.

  • Shared behaviour placement

    Full marks when the describe sentence is written once on the shared type and reused by every discount, calling the calculation and the label rather than repeating either. Lose points when the sentence is duplicated per discount, assembled inside the engine, or when adding a fourth kind would mean editing existing describe logic.

  • Structure and naming

    Full marks when each discount holds its own configuration so two of the same kind can coexist, the flat discount cannot drive a price below zero, and names are descriptive with no dead code. Lose points when a discount's setting is stored on the engine, when the clamp is missing or applied by the caller, or for printing to stdout.

Passing every test is not enough on its own. A submission is accepted only when the design also clears the bar.

Hints

Loading...
CallReturns
new PricingEngine()null
addPercentage(20)0
addFlat(15)1
describe(0, 100)"20% off: $100.00 -> $80.00"
describe(1, 100)"$15.00 off: $100.00 -> $85.00"
priceAfter(0, 100)80

A 20% discount and a $15 discount are stored at indices 0 and 1. On a price of 100 the first leaves 80 and the second leaves 85, and each describes itself with its own label.

Run checks these cases. Submit also runs a larger hidden set.