面試題 Shopping Receipt

Objective

Write a program to print receipt for a shopping cart including sales tax.

Customers shop from different states of US, and sales tax is applied based on location and product category.

Sales tax = roundup(price * quantity * sales tax rate)

Certain product categories are exempt from sales tax (means tax will be 0), and sales tax amount should be rounded up to the nearest 0.05 (e.g. 1.13->1.15, 1.16->1.20, 1.151->1.20).

The interactive UI is not required, at minimum you can implement code method and use parameters as input or read input value from file.

Input

The input of the program includes: product name, price, quantity and location of the purchase.

All other information, such as tax rates and product categories, is not part of the input and can be stored/initialized within the program or as part of configuration settings.

Output

The program should print the list of items customer purchased, including name/qty/price, subtotal, sales tax, and total, by following format of use cases.

Tax rates

In California (CA), sales tax rate is 9.75%, food is exempt.

In New York (NY), sales tax rate is 8.875%, food and clothing are exempt.


Please use JAVA. Unit test is a plus.

Use case 1:

Input: Location: CA, 1 book at 17.99, 1 potato chips at 3.99
Output:

item              price        qty

book             $17.99          1
potato chips      $3.99          1
subtotal:                   $21.98
tax:                         $1.80
total:                      $23.78

Use case 2:

Input: Location: NY, 1 book at 17.99, 3 pencils at 2.99
Output:

item              price        qty

book             $17.99          1
pencil            $2.99          3
subtotal:                   $26.96
tax:                         $2.40
total:                      $29.36

Use case 3:

Input: Location: NY, 2 pencils at 2.99, 1 shirt at 29.99
Output:

item              price        qty

pencil            $2.99          2
shirt            $29.99          1
subtotal:                   $35.97
tax:                         $0.55
total:                      $36.52

答案

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/**
 * all in one program based on jdk 21
 */
public class Cart {

    enum Location {
        CA, NY
    }

    enum Category {
        FOOD, CLOTHING, OTHER
    }

    static class Product {
        Integer quantity;
        String name;
        BigDecimal price;

        public Product(Integer quantity, String name, Double price) {
            this.quantity = quantity;
            this.name = name;
            this.price = BigDecimal.valueOf(price);
        }
    }

    Location location;
    List<Product> products;
    Map<Location, BigDecimal> taxRateMap;
    Map<String, Category> productCategoryMap;

    Cart(Location location, Product... products) {
        this.location = location;
        this.products = List.of(products);

        taxRateMap = Map.of(
                Location.CA, BigDecimal.valueOf(9.75),
                Location.NY, BigDecimal.valueOf(8.875)
        );

        productCategoryMap = Map.of(
                "book", Category.OTHER,
                "potato chips", Category.FOOD,
                "pencil", Category.OTHER,
                "shirt", Category.CLOTHING
        );
    }

    // output the formatted content
    public void printReceipt() {
        BigDecimal subtotal = BigDecimal.ZERO;
        BigDecimal tax = BigDecimal.ZERO;
        BigDecimal total;

        System.out.printf("%-15s %8s %12s%n", "item", "price", "qty");
        System.out.println();

        for (Product product : products) {
            BigDecimal itemTotal = product.price.multiply(BigDecimal.valueOf(product.quantity.longValue()));
            subtotal = subtotal.add(itemTotal);
            tax = tax.add(countTax(product.name, itemTotal));

            System.out.printf("%-15s %8s %12s%n", product.name, "$" + product.price, product.quantity);
        }

        total = subtotal.add(tax);

        System.out.printf("%-15s %21s%n", "subtotal:", "$" + subtotal);
        System.out.printf("%-15s %21s%n", "tax:", "$" + tax);
        System.out.printf("%-15s %21s%n", "total:", "$" + total);
    }

    // count tax by location and category
    private BigDecimal countTax(String productName, BigDecimal price) {
        Category category = productCategoryMap.get(productName);
        BigDecimal taxRate = taxRateMap.get(location);

        if (location == Location.CA && category == Category.FOOD ||
            location == Location.NY && category == Category.FOOD ||
            location == Location.NY && category == Category.CLOTHING
        ) {
            taxRate = BigDecimal.ZERO;
        }

        BigDecimal tax = price.multiply(taxRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.UP);
        return tax.divide(BigDecimal.valueOf(0.05), 0, RoundingMode.UP).multiply(BigDecimal.valueOf(0.05));
    }

    // unit test
    public static void main(String[] args) {
        System.out.println("Use case 1");
        new Cart(Location.CA,
                new Product(1, "book", 17.99),
                new Product(1, "potato chips", 3.99)
        ).printReceipt();
        System.out.println();

        System.out.println("Use case 2");
        new Cart(Location.NY,
                new Product(1, "book", 17.99),
                new Product(3, "pencil", 2.99)
        ).printReceipt();
        System.out.println();

        System.out.println("Use case 3");
        new Cart(Location.NY,
                new Product(2, "pencil", 2.99),
                new Product(1, "shirt", 29.99)
        ).printReceipt();
        System.out.println();
    }
}

解析

  1. 考英文閱讀理解能力
  2. 考物件導向概念:參數、傳值
  3. 考浮點數計算:BigDecimal、round、scale
  4. 考文字排版:printf

相較於資料結構那類,還是比較喜歡這種題目。
因為沒有絕對答案,自由度更大,而且貼近實際開發工作。

發佈留言