Refactor a Shopping Cart to Print Grouped, Promoted, Sorted Receipts
Company: Playstation
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
This object-oriented coding exercise has a 30-minute time box and starts from existing code. A `ShoppingCart` class keeps the items a customer has scanned in a list and has methods such as `addItem` and `removeItem`, and code that prints a receipt from the cart is already in place. Items arrive as a stream of strings, and they must be turned into a receipt. Implement the four requirements below in order, each one extending the previous one. Expect most of the work to be in the cart class rather than in the printing.
For the examples, assume these unit prices (the exercise's own catalog was not reported):
```text
Unit prices: cheese 4.00 bread 2.50 apple 0.75
Stream: "cheese", "bread", "cheese", "apple", "cheese"
```
### Clarifying Questions
- What does each string contain: only an item name, or a name with a price or quantity? Where do prices come from?
- How should prices be stored and printed (currency, number of decimal places)?
- What should removing an item that is not in the cart do?
- Must the itemized receipt from requirement 1 still be printable after requirement 2 changes the format?
- Are item names case-sensitive, and should surrounding whitespace be trimmed?
### Part 1 — Itemized receipt with a total
Print every item on its own line with its price, in the order scanned, and finish with a line showing the total price.
```text
cheese 4.00
bread 2.50
cheese 4.00
apple 0.75
cheese 4.00
Total 15.25
```
```hint Exact money
Choose a representation for prices that stays exact when many of them are added together.
```
#### What This Part Should Cover
- Reading the stream into the cart, including blank or unknown entries
- Exact money arithmetic and formatting
- The total line
### Part 2 — Group items by type
Change the receipt to one line per item type, showing the name, the quantity, and the unit price times the quantity, for example `cheese, 3, 4.00 x3` for three cheeses. Adding and removing items must keep working.
```text
cheese, 3, 4.00 x3
bread, 1, 2.50 x1
apple, 1, 0.75 x1
Total 15.25
```
The order of the lines is not specified yet; requirement 4 fixes it.
```hint Store what the receipt needs
Decide what the cart should keep for each item type so that adding an item, removing an item and printing a line never have to scan every unit scanned so far.
```
#### What This Part Should Cover
- A change to how the cart stores items, and why
- Rewritten add and remove methods, including removing the last unit of a type
- The cost of each cart operation before and after the change
### Part 3 — Buy three, get two free
Add a "buy three, get two free" promotion for one specific item, and adjust that item's price and quantity on the receipt accordingly. Other items are unaffected.
```hint Where the discount lives
Decide whether the promotion should change stored data when an item is added, or be applied when the receipt is computed, and test your choice against removing an item.
```
#### Clarifying Questions for this Part
- Does "buy three, get two free" mean that two units are free in every group of five scanned, or that every three units bought add two free units to the quantity?
- Does a partial group earn anything, for example when four units are scanned?
- Should the receipt show the savings on a separate line?
- Can promotions apply to more than one item, or more than one promotion to the same item?
#### What This Part Should Cover
- The promotion as its own abstraction rather than special cases in the cart or the printer
- Correct arithmetic for full and partial groups
- Correct behavior when a promoted item is removed
### Part 4 — Sort the receipt alphabetically
Print the receipt lines in alphabetical order of item name.
```text
apple, 1, 0.75 x1
bread, 1, 2.50 x1
cheese, 3, 4.00 x3
Total 15.25
```
```hint Sorted always, or sorted on demand
Compare keeping the items ordered at all times with sorting them only when the receipt is printed.
```
#### What This Part Should Cover
- Where the ordering is enforced, and its cost
- How ties and letter case are handled
### What a Strong Answer Covers
- Clarifies the input format, the money representation and the promotion's meaning before coding
- Refactors in small steps, keeping each requirement working
- Clear responsibilities: cart storage, pricing and promotions, receipt formatting
- Correct add and remove behavior, including the edge cases
- Working, quickly tested code within the 30-minute time box
### Follow-up Questions
- Promotions now change weekly and several can apply to one item. How do you choose which one applies, and where do the promotions come from?
- Add a promotion across item types, such as a discount when bread and cheese are bought together. What changes in your design?
- Several checkout lanes scan into their own carts at once, sharing one price catalog and one promotion table that can change during the day. What must be thread-safe, and which prices and promotions should a receipt use?
- How would you unit-test the receipt logic without comparing printed output by eye?
Overview: A 30-minute object-oriented exercise that turns a stream of item names into a printed receipt, then extends it to group items by type, apply a buy-three-get-two-free promotion and sort the lines alphabetically. It tests refactoring a shopping cart's storage and its add and remove methods, exact money handling and clean class design.
Read the full Playstation Software Engineer interview experience this question came from