PracHub
QuestionsPremiumLearningGuidesCheatsheetNEWCoaches

Quick Overview

This question evaluates event-stream processing, stateful per-user counting, and time-window filtering competencies, requiring correctness with ordered inputs and enforcement of per-offer redemption constraints.

  • easy
  • Affirm
  • Coding & Algorithms
  • Software Engineer

Compute Available Offers per User

Company: Affirm

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: easy

Interview Round: Technical Screen

You are given a set of promotional offers and a CSV event stream read from standard input. Each **Offer** has the following fields: - `name`: string - `start_at`: timestamp - `end_at`: timestamp - `user_max_redemption_count`: integer Each **OfferEvent** row has: - `user_id`: string - `offer_name`: string - `event_time`: timestamp Each event represents one redemption attempt by a user for an offer. Process the events **in the order they appear**. An event should be counted only if all of the following are true: 1. the referenced offer exists, 2. the event time is within the offer's validity window, inclusive: `start_at <= event_time <= end_at`, 3. before applying the event, that user has redeemed the offer fewer than `user_max_redemption_count` times. You are also given a `PROCESSING_DATE`. After all events are processed, compute the offers that are still available to each user. An offer is available to a user on `PROCESSING_DATE` if: - the offer is still active on that date: `start_at <= PROCESSING_DATE <= end_at`, and - the user's counted redemptions for that offer are still below `user_max_redemption_count`. Return a mapping from each user to the list of currently available offer names. If a user appears in the input but has no available offers, return an empty list for that user. Example output: ```python { 'user1': ['Offer_1', 'Offer_2'], 'user2': ['Offer_1'] } ``` For deterministic output, sort each user's offer list lexicographically.

Quick Answer: This question evaluates event-stream processing, stateful per-user counting, and time-window filtering competencies, requiring correctness with ordered inputs and enforcement of per-offer redemption constraints.

You are given a list of promotional offers and a CSV event stream. Each event is one redemption attempt by a user for an offer. Process the events strictly in the order they appear in the CSV. An event counts only if all of the following are true before applying it: 1. the referenced offer exists, 2. the event time is within the offer window, inclusive: start_at <= event_time <= end_at, 3. that user has redeemed the offer fewer than user_max_redemption_count times. After all events are processed, compute which offers are still available to each user on processing_date. An offer is available to a user if: - the offer is active on processing_date, inclusive, and - the user's counted redemptions for that offer are still below the per-user maximum. Important details: - Return results only for users who appear at least once in the CSV input, even if all of their events are invalid. - A user can still have an offer available even if they never attempted that offer. - Sort each user's available offer names lexicographically. For this function-based version of the problem: - offers is a list of tuples: (name, start_at, end_at, user_max_redemption_count) - events_csv is a single CSV string with header: user_id,offer_name,event_time - processing_date is an ISO timestamp string

Constraints

  • 1 <= len(offers) <= 10^4
  • 0 <= number of event rows in events_csv <= 2 * 10^5
  • 0 <= user_max_redemption_count <= 10^9
  • Offer names are unique
  • All timestamps are valid ISO-8601 strings without timezones
  • When non-empty, events_csv contains the header: user_id,offer_name,event_time

Examples

Input: ([('Offer_1', '2024-01-01T00:00:00', '2024-01-31T23:59:59', 2), ('Offer_2', '2024-01-10T00:00:00', '2024-01-20T23:59:59', 1), ('Offer_3', '2024-02-01T00:00:00', '2024-02-10T23:59:59', 5)], 'user_id,offer_name,event_time\nu1,Offer_1,2024-01-05T10:00:00\nu1,Offer_1,2024-01-06T10:00:00\nu1,Offer_1,2024-01-07T10:00:00\nu1,Offer_2,2024-01-15T12:00:00\nu2,Offer_1,2024-01-08T09:00:00\nu2,Missing,2024-01-08T09:05:00\nu3,Offer_2,2024-01-09T09:00:00', '2024-01-15T00:00:00')

Expected Output: {'u1': [], 'u2': ['Offer_1', 'Offer_2'], 'u3': ['Offer_1', 'Offer_2']}

Explanation: u1 has exhausted both active offers. u2 has one counted redemption on Offer_1 and none on Offer_2, so both are still available. u3 appears in the CSV via an invalid early event, but still gets all currently active offers with remaining capacity.

Input: ([('B', '2024-03-01T00:00:00', '2024-03-10T00:00:00', 1), ('A', '2024-03-05T00:00:00', '2024-03-20T00:00:00', 2)], 'user_id,offer_name,event_time\nu1,B,2024-03-01T00:00:00\nu1,A,2024-03-05T00:00:00\nu1,A,2024-03-20T00:00:00\nu2,B,2024-02-29T23:59:59', '2024-03-10T00:00:00')

Expected Output: {'u1': [], 'u2': ['A', 'B']}

Explanation: This checks inclusive boundaries. u1 redeems B exactly at its start and A exactly at both its start/end bounds, reaching both limits. u2's attempt on B is before the offer starts, so it does not count; both active offers remain available to u2, sorted lexicographically.

Input: ([('X', '2024-06-01T00:00:00', '2024-06-30T23:59:59', 1)], 'user_id,offer_name,event_time\n', '2024-06-15T00:00:00')

Expected Output: {}

Explanation: There are no event rows, so no users appear in the input and the result is an empty mapping.

Input: ([('Freebie', '2024-05-01T00:00:00', '2024-05-31T23:59:59', 0), ('Spring', '2024-05-01T00:00:00', '2024-05-31T23:59:59', 1), ('Expired', '2024-04-01T00:00:00', '2024-04-30T23:59:59', 10)], 'user_id,offer_name,event_time\nu1,Freebie,2024-05-10T10:00:00\nu1,Expired,2024-04-15T10:00:00\nu2,Unknown,2024-05-10T10:00:00', '2024-05-20T00:00:00')

Expected Output: {'u1': ['Spring'], 'u2': ['Spring']}

Explanation: Freebie has a per-user max of 0, so it is never available and its event never counts. Expired is not active on the processing date. Both users therefore only have Spring available.

Input: ([('Old', '2024-01-01T00:00:00', '2024-01-31T23:59:59', 5), ('Future', '2024-03-01T00:00:00', '2024-03-31T23:59:59', 2)], 'user_id,offer_name,event_time\nu1,Old,2024-01-10T10:00:00\nu2,Future,2024-02-28T10:00:00', '2024-02-15T00:00:00')

Expected Output: {'u1': [], 'u2': []}

Explanation: Old has already ended by the processing date and Future has not started yet, so no offers are active. Users who appear in the CSV must still be present in the output with empty lists.

Hints

  1. Use a hash map keyed by offer_name so you can validate an event and fetch its window and limit in O(1). Track redemption counts by (user_id, offer_name).
  2. When building the final answer, do not look only at offers a user has already tried. Any active offer with remaining capacity is still available to that user.
Last updated: Apr 19, 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

  • Determine Redeemable Promotion Offers - Affirm (medium)
  • Aggregate loans and match repayments - Affirm (medium)
  • Implement a timestamped map - Affirm (medium)
  • Detect fraud events and extract PII - Affirm (medium)
  • Compute Balances and Minimize Settlements - Affirm (hard)