PracHub
QuestionsPremiumLearningGuidesCheatsheetNEWCoaches

Quick Overview

This question evaluates software design and algorithmic problem-solving skills focused on pricing logic, including handling financial rounding, discount ordering, eligibility criteria across item categories, and time/space complexity analysis.

  • Medium
  • Applied Intuition
  • Coding & Algorithms
  • Software Engineer

Design a coupon pricing engine

Company: Applied Intuition

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: Medium

Interview Round: Technical Screen

Design and implement a coupon application engine for a shopping cart. Each Item has id, category, and unitPrice. A Coupon has: applicableCategories (one or more), minimumTotalItemRequirement, minimumTotalPriceRequirement, percentageDiscount (0– 100), and valueDiscount (flat currency). Part 1: Given one Coupon and a list of Items in the cart, compute the final cart price after applying the coupon once, honoring minimum requirements; specify how you handle rounding and the order of applying percentage vs. flat discounts. Part 2: Extend your design to support Coupons that apply to multiple categories within the same cart; explain data structures, class interfaces, and time/space complexity; provide unit tests and edge cases (e.g., no eligible items, overlapping categories, zero or negative totals).

Quick Answer: This question evaluates software design and algorithmic problem-solving skills focused on pricing logic, including handling financial rounding, discount ordering, eligibility criteria across item categories, and time/space complexity analysis.

Part 1: Apply One Coupon to a Single Category

You are given a shopping cart and one coupon. Each item is a dictionary with keys 'id', 'category', and 'unit_price', where 'unit_price' is a non-negative integer number of cents. The coupon is a dictionary with keys 'applicable_category', 'minimum_total_item_requirement', 'minimum_total_price_requirement', 'percentage_discount', and 'value_discount'. The coupon can be applied at most once, and only to items whose category matches 'applicable_category'. First collect the eligible items in that category. The coupon is valid only if the eligible item count and eligible subtotal both meet their minimum requirements. If valid, discount only the eligible subtotal, not the whole cart. Apply the percentage discount first, rounding half up to the nearest cent, then subtract the flat value discount. The discounted eligible subtotal cannot go below 0. Return the final cart total in cents.

Constraints

  • 0 <= len(items) <= 200000
  • 0 <= unit_price <= 10^9
  • 0 <= minimum_total_item_requirement <= len(items)
  • 0 <= minimum_total_price_requirement <= 10^14
  • 0 <= percentage_discount <= 100
  • 0 <= value_discount <= 10^14
  • All prices are in cents.

Examples

Input: ([{'id': 1, 'category': 'A', 'unit_price': 1000}, {'id': 2, 'category': 'A', 'unit_price': 2000}, {'id': 3, 'category': 'B', 'unit_price': 500}], {'applicable_category': 'A', 'minimum_total_item_requirement': 2, 'minimum_total_price_requirement': 2500, 'percentage_discount': 10, 'value_discount': 300})

Expected Output: 2900

Explanation: Eligible A subtotal is 3000. Apply 10% off => 300 cents discount, then 300 cents flat discount, so A items become 2400. Add B item 500 => 2900.

Input: ([{'id': 1, 'category': 'A', 'unit_price': 999}], {'applicable_category': 'A', 'minimum_total_item_requirement': 1, 'minimum_total_price_requirement': 0, 'percentage_discount': 15, 'value_discount': 0})

Expected Output: 849

Explanation: 15% of 999 is 149.85 cents, which rounds half up to 150 cents. Final total is 999 - 150 = 849.

Input: ([{'id': 1, 'category': 'A', 'unit_price': 1000}, {'id': 2, 'category': 'B', 'unit_price': 500}], {'applicable_category': 'A', 'minimum_total_item_requirement': 2, 'minimum_total_price_requirement': 1000, 'percentage_discount': 20, 'value_discount': 100})

Expected Output: 1500

Explanation: Only one eligible A item exists, so the minimum item requirement is not met. No discount is applied.

Input: ([{'id': 1, 'category': 'A', 'unit_price': 500}, {'id': 2, 'category': 'B', 'unit_price': 700}], {'applicable_category': 'A', 'minimum_total_item_requirement': 1, 'minimum_total_price_requirement': 0, 'percentage_discount': 50, 'value_discount': 400})

Expected Output: 700

Explanation: Eligible subtotal is 500. After 50% off, it becomes 250. Subtract 400 more, clamp at 0. Final total is only the B item: 700.

Input: ([], {'applicable_category': 'A', 'minimum_total_item_requirement': 1, 'minimum_total_price_requirement': 0, 'percentage_discount': 10, 'value_discount': 100})

Expected Output: 0

Explanation: Empty cart edge case.

Solution

def solution(items, coupon):
    total = 0
    eligible_total = 0
    eligible_count = 0
    target_category = coupon['applicable_category']

    for item in items:
        price = item['unit_price']
        total += price
        if item['category'] == target_category:
            eligible_total += price
            eligible_count += 1

    if eligible_count < coupon['minimum_total_item_requirement']:
        return total
    if eligible_total < coupon['minimum_total_price_requirement']:
        return total

    percent = coupon['percentage_discount']
    value_discount = coupon['value_discount']

    percent_discount_amount = (eligible_total * percent + 50) // 100
    discounted_eligible_total = eligible_total - percent_discount_amount - value_discount
    if discounted_eligible_total < 0:
        discounted_eligible_total = 0

    return total - eligible_total + discounted_eligible_total

Time complexity: O(n), where n is the number of items.. Space complexity: O(1), excluding the input..

Hints

  1. Compute the full cart total and the eligible subtotal separately.
  2. For half-up rounding in cents, the percentage discount on subtotal S with percent P can be computed as (S * P + 50) // 100.

Part 2: Multi-Category Coupon Engine with Overlapping Coupons

You are given a shopping cart and a list of coupons to process in order. Each item is a dictionary with keys 'id', 'category', and 'unit_price', where 'unit_price' is a non-negative integer number of cents. Each coupon is a dictionary with keys 'applicable_categories', 'minimum_total_item_requirement', 'minimum_total_price_requirement', 'percentage_discount', and 'value_discount'. A coupon applies to all currently unused items whose category appears in 'applicable_categories'. Its minimum requirements are checked against the combined count and subtotal across those currently unused eligible items. If valid, apply the coupon once to that combined subtotal: percentage discount first with half-up rounding to the nearest cent, then flat discount, clamped at 0. After a coupon is successfully applied, every item it used becomes unavailable for later coupons. If a coupon does not meet its requirements, it is skipped and those items remain available. Duplicate category names inside one coupon should be treated as one category. Return the final cart total in cents after processing all coupons in the given order.

Constraints

  • 0 <= len(items) <= 200000
  • 0 <= len(coupons) <= 200000
  • 1 <= total number of category names across all coupons <= 200000, for non-empty coupon lists
  • 0 <= unit_price <= 10^9
  • 0 <= minimum_total_item_requirement <= len(items)
  • 0 <= minimum_total_price_requirement <= 10^14
  • 0 <= percentage_discount <= 100
  • 0 <= value_discount <= 10^14
  • All prices are in cents.

Examples

Input: ([{'id': 1, 'category': 'grocery', 'unit_price': 500}, {'id': 2, 'category': 'beauty', 'unit_price': 300}, {'id': 3, 'category': 'toy', 'unit_price': 200}], [{'applicable_categories': ['grocery', 'beauty'], 'minimum_total_item_requirement': 2, 'minimum_total_price_requirement': 700, 'percentage_discount': 10, 'value_discount': 100}])

Expected Output: 820

Explanation: The coupon combines grocery and beauty items for subtotal 800. After 10% off and then 100 cents flat off, they become 620. Add toy item 200 => 820.

Input: ([{'id': 1, 'category': 'A', 'unit_price': 1000}, {'id': 2, 'category': 'B', 'unit_price': 600}, {'id': 3, 'category': 'B', 'unit_price': 400}, {'id': 4, 'category': 'C', 'unit_price': 500}], [{'applicable_categories': ['A', 'B'], 'minimum_total_item_requirement': 3, 'minimum_total_price_requirement': 1800, 'percentage_discount': 10, 'value_discount': 100}, {'applicable_categories': ['B', 'C'], 'minimum_total_item_requirement': 1, 'minimum_total_price_requirement': 0, 'percentage_discount': 20, 'value_discount': 0}])

Expected Output: 2100

Explanation: First coupon uses all remaining A and B items: 2000 -> 1700 after discounts. Those items are consumed. Second coupon can only use C, so 500 -> 400. Final total is 1700 + 400 = 2100.

Input: ([{'id': 1, 'category': 'A', 'unit_price': 400}, {'id': 2, 'category': 'B', 'unit_price': 400}], [{'applicable_categories': ['A', 'B'], 'minimum_total_item_requirement': 3, 'minimum_total_price_requirement': 0, 'percentage_discount': 50, 'value_discount': 0}, {'applicable_categories': ['A'], 'minimum_total_item_requirement': 1, 'minimum_total_price_requirement': 0, 'percentage_discount': 25, 'value_discount': 0}])

Expected Output: 700

Explanation: The first coupon is skipped because it needs 3 eligible items but only 2 are available. The second coupon then discounts category A from 400 to 300. Category B stays 400.

Input: ([{'id': 1, 'category': 'A', 'unit_price': 300}, {'id': 2, 'category': 'B', 'unit_price': 200}], [{'applicable_categories': ['A', 'B', 'A'], 'minimum_total_item_requirement': 2, 'minimum_total_price_requirement': 0, 'percentage_discount': 50, 'value_discount': 400}])

Expected Output: 0

Explanation: Duplicate 'A' should not double count. Eligible subtotal is 500, then 50% off gives 250, then subtract 400 and clamp at 0.

Input: ([{'id': 1, 'category': 'X', 'unit_price': 500}], [{'applicable_categories': ['A', 'B'], 'minimum_total_item_requirement': 1, 'minimum_total_price_requirement': 0, 'percentage_discount': 10, 'value_discount': 100}])

Expected Output: 500

Explanation: No eligible items match the coupon categories, so the cart total is unchanged.

Solution

def solution(items, coupons):
    from collections import defaultdict

    category_count = defaultdict(int)
    category_total = defaultdict(int)
    remaining_total = 0

    for item in items:
        category = item['category']
        price = item['unit_price']
        category_count[category] += 1
        category_total[category] += price
        remaining_total += price

    for coupon in coupons:
        categories = set(coupon['applicable_categories'])

        eligible_count = 0
        eligible_total = 0
        for category in categories:
            eligible_count += category_count.get(category, 0)
            eligible_total += category_total.get(category, 0)

        if eligible_count < coupon['minimum_total_item_requirement']:
            continue
        if eligible_total < coupon['minimum_total_price_requirement']:
            continue

        percent = coupon['percentage_discount']
        value_discount = coupon['value_discount']
        percent_discount_amount = (eligible_total * percent + 50) // 100
        discounted_total = eligible_total - percent_discount_amount - value_discount
        if discounted_total < 0:
            discounted_total = 0

        remaining_total = remaining_total - eligible_total + discounted_total

        for category in categories:
            category_count[category] = 0
            category_total[category] = 0

    return remaining_total

Time complexity: O(n + t), where n is the number of items and t is the total number of category names mentioned across all coupons.. Space complexity: O(k), where k is the number of distinct categories present in the cart or coupons..

Hints

  1. Aggregate the remaining item count and subtotal by category so each coupon can be evaluated without rescanning every item.
  2. When a coupon succeeds, all remaining items in its listed categories are consumed, so their category aggregates can be zeroed out.
Last updated: May 9, 2026

Loading coding console...

PracHub

Master your tech interviews with 7,500+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Design a nested transaction store - Applied Intuition (Medium)
  • Implement transactional key–value store - Applied Intuition (Medium)
  • Find grid cell minimizing sum distances - Applied Intuition (Medium)
  • Design a transactional in-memory key–value store - Applied Intuition (Medium)
  • Find duplicate files by size - Applied Intuition (Medium)