Strategy Pattern: Customer Discounts

Problem

Each input line has a customer type and an amount. Customer types: REGULAR pays 100%, STUDENT pays 90%, SENIOR pays 80%, VIP pays 70%. Print the amount to pay for each line (cut the decimals: use integer division). For an unknown type print Error: unknown customer. Use the Strategy pattern: one small object per discount rule, chosen by the customer type, instead of a long if / else chain.

Constraints

  • 1 <= lines <= 1000
  • 0 <= amount <= 10^9

Examples

Input

REGULAR 100
STUDENT 100

Output

100
90

Solutions

Best approachTime O(lines)Space O(lines)

The Strategy pattern puts each rule in its own object (or function) and chooses one at run time. The calling code stays the same when a new rule is added (open/closed principle).

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process commands line by line.
 * Input   : Several lines of commands.
 * Output  : The amount to pay for each line.
 * Approach: Choose a rule object by key.
 * Time    : O(lines)
 * Space   : O(lines)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: The strategy interface. Every discount rule has the same method.
        interface DiscountStrategy {
            long priceToPay(long amount);
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        // Step 2: A map from the customer type to its strategy. A new customer type only needs a new entry here.
        java.util.Map<String, DiscountStrategy> strategies = new java.util.HashMap<>();
        strategies.put("REGULAR", amount -> amount * 100 / 100);
        strategies.put("STUDENT", amount -> amount * 90 / 100);
        strategies.put("SENIOR", amount -> amount * 80 / 100);
        strategies.put("VIP", amount -> amount * 70 / 100);

        String[] output = new String[lines.length];
        for (int i = 0; i < lines.length; i++) {
            String[] parts = lines[i].split(" ");

            // Step 3: Pick the strategy and use it. There is no if / else chain.
            DiscountStrategy strategy = strategies.get(parts[0]);
            if (strategy == null) {
                output[i] = "Error: unknown customer";
            } else {
                output[i] = String.valueOf(strategy.priceToPay(Long.parseLong(parts[1])));
            }
        }
        return output;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (2)
  1. What is the common method of all strategies?
  2. How does a map replace an if / else chain?