Shopping Cart Checkout

Problem

Build a shopping cart. Prices are whole numbers (cents). Commands: ADD name price qty (add qty items; if the item is already in the cart, only the quantity grows), REMOVE name qty (print error if the cart has fewer than qty of that item; an item with quantity 0 leaves the cart), COUPON percent (set the discount percent, replacing the old one) and TOTAL. ADD, REMOVE and COUPON print ok (or error). TOTAL prints three numbers: the subtotal, the discount (subtotal * percent / 100, rounded down) and the total to pay.

Constraints

  • 1 <= lines <= 1000
  • 0 <= percent <= 100

Examples

Input

ADD pen 150 4
TOTAL
COUPON 10
TOTAL

Output

ok
600 0 600
ok
600 60 540

Solutions

Best approachTime O(n * items)Space O(items)

A Cart class keeps items and the coupon together and exposes the four operations. The price rule (round down the discount) lives in one method, so it is easy to change and to test.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several command lines.
 * Output  : One result per command.
 * Approach: Cart class.
 * Time    : O(n * items)
 * Space   : O(items)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: The cart keeps its items and the coupon. The rules for the money are in one place.
        static class Cart {
            private final java.util.Map<String, long[]> items = new java.util.LinkedHashMap<String, long[]>();
            private long percent = 0;

            void add(String name, long price, long qty) {
                long[] item = items.get(name);
                if (item == null) {
                    items.put(name, new long[] {price, qty});
                } else {
                    item[1] += qty;
                }
            }

            boolean remove(String name, long qty) {
                long[] item = items.get(name);
                if (item == null || item[1] < qty) {
                    return false;
                }
                item[1] -= qty;
                if (item[1] == 0) {
                    items.remove(name);
                }
                return true;
            }

            void coupon(long percent) {
                this.percent = percent;
            }

            // Step 2: Subtotal, then discount rounded down, then total.
            String total() {
                long subtotal = 0;
                for (long[] item : items.values()) {
                    subtotal += item[0] * item[1];
                }
                long discount = subtotal * percent / 100;
                return subtotal + " " + discount + " " + (subtotal - discount);
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        Cart cart = new Cart();
        String[] output = new String[lines.length];
        for (int i = 0; i < lines.length; i++) {
            String[] part = lines[i].split(" ");
            if (part[0].equals("ADD")) {
                cart.add(part[1], Long.parseLong(part[2]), Long.parseLong(part[3]));
                output[i] = "ok";
            } else if (part[0].equals("REMOVE")) {
                output[i] = cart.remove(part[1], Long.parseLong(part[2])) ? "ok" : "error";
            } else if (part[0].equals("COUPON")) {
                cart.coupon(Long.parseLong(part[1]));
                output[i] = "ok";
            } else {
                output[i] = cart.total();
            }
        }
        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. Why keep money in whole cents?
  2. Where is the discount rounded?