PracHub
QuestionsCoachesLearningGuidesInterview Prep

Quick Overview

A Stripe software-engineer take-home that builds up a credit-card validation suite using the Luhn checksum and VISA/MASTERCARD/AMEX brand patterns. It progresses from exact validation and brand identification to an UNKNOWN fallback, analytic wildcard counting per brand, and single-error correction that enumerates all valid original numbers.

  • Medium
  • Stripe
  • Coding & Algorithms
  • Software Engineer

Implement Luhn-based card validation and inference

Company: Stripe

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: Medium

Interview Round: Take-home Project

##### Question Implement a set of utilities for credit-card validation and inference using the Luhn checksum algorithm and standard brand patterns. **Brand patterns:** - **VISA** — 16 digits, starts with `4` - **MASTERCARD** — 16 digits, starts with `51`, `52`, `53`, `54`, or `55` - **AMEX** — 15 digits, starts with `34` or `37` **Tasks:** 1. Given a digit-only card-number string, return whether it passes the Luhn checksum and, if valid, which brand it belongs to. Possible outputs: `["INVALID_CHECKSUM", "VISA", "MASTERCARD", "AMEX"]`. 2. Extend task 1 so that a number passing the Luhn check but matching none of the three known brand patterns is labeled `"UNKNOWN"`. 3. Allow the input to contain `*` wildcards, each standing for any single digit (e.g., `"****424242424242"`). Return the count of possible valid card numbers per brand, formatted as a list of `"BRAND,count"` pairs (e.g., `["VISA,1", "MASTERCARD,10"]`). A single pattern may be consistent with more than one brand, so report a count for every brand it could represent. Note: once a brand is fixed, the number of valid completions equals `10^(number_of_asterisks - 1)`, because Luhn fixes one degree of freedom. 4. Error-correction: given an observed string whose trailing `?` indicates that exactly one error occurred to the preceding digits — one of {changed digit, removed digit, added digit, or transposition of two adjacent digits} (e.g., `"4333220284765319?"`) — enumerate every original card number (and its brand) that was valid before the error and that could have produced the observed string.

Quick Answer: A Stripe software-engineer take-home that builds up a credit-card validation suite using the Luhn checksum and VISA/MASTERCARD/AMEX brand patterns. It progresses from exact validation and brand identification to an UNKNOWN fallback, analytic wildcard counting per brand, and single-error correction that enumerates all valid original numbers.

Luhn Card Validation + Brand Identification

Given a digit-only card-number string, return whether it passes the Luhn checksum and, if it passes, which of the three known brands it belongs to. Brand patterns: - VISA: 16 digits, starts with 4 - MASTERCARD: 16 digits, starts with 51, 52, 53, 54, or 55 - AMEX: 15 digits, starts with 34 or 37 Luhn checksum: walking the digits right-to-left, double every second digit; if a doubled value exceeds 9, subtract 9. The number is valid iff the total is divisible by 10. Return one of: "INVALID_CHECKSUM", "VISA", "MASTERCARD", "AMEX". A number that fails Luhn, OR passes Luhn but matches none of the three brand patterns, returns "INVALID_CHECKSUM" in this task.

Constraints

  • Input contains only ASCII digit characters 0-9.
  • Length is not guaranteed to be 15 or 16; non-matching lengths simply fail the brand check.
  • Empty string is Luhn-valid (sum 0) but matches no brand -> INVALID_CHECKSUM.

Examples

Input: ('4242424242424242',)

Expected Output: 'VISA'

Explanation: 16 digits, starts with 4, Luhn-valid -> VISA (a real Visa test card).

Input: ('5555555555554444',)

Expected Output: 'MASTERCARD'

Explanation: 16 digits, starts with 55, Luhn-valid -> MASTERCARD.

Input: ('371449635398431',)

Expected Output: 'AMEX'

Explanation: 15 digits, starts with 37, Luhn-valid -> AMEX.

Input: ('4242424242424241',)

Expected Output: 'INVALID_CHECKSUM'

Explanation: Last digit changed; the Luhn checksum no longer holds.

Input: ('1234567812345670',)

Expected Output: 'INVALID_CHECKSUM'

Explanation: Luhn-valid but starts with 1 and matches no brand pattern -> INVALID_CHECKSUM in task 1.

Input: ('378282246310005',)

Expected Output: 'AMEX'

Explanation: 15 digits, starts with 37, Luhn-valid -> AMEX.

Hints

  1. Write a reusable luhn_ok(t) helper first; tasks 2-4 all reuse it.
  2. Process digits right-to-left and double every second one, subtracting 9 when the doubled digit exceeds 9.
  3. Brand identification only happens AFTER Luhn passes. A Luhn-valid number with an unknown prefix/length is still INVALID_CHECKSUM in this first task.

Card Validation with UNKNOWN Fallback

Extend the previous classifier: a number that PASSES the Luhn checksum but matches none of the three known brand patterns (VISA / MASTERCARD / AMEX) should be labeled "UNKNOWN" rather than rejected. Return one of: "INVALID_CHECKSUM", "VISA", "MASTERCARD", "AMEX", "UNKNOWN". - Fails Luhn -> "INVALID_CHECKSUM". - Passes Luhn and matches a brand -> that brand. - Passes Luhn but matches no brand -> "UNKNOWN".

Constraints

  • Input contains only ASCII digit characters 0-9.
  • The only behavioral change from task 1 is the final fallthrough: UNKNOWN instead of INVALID_CHECKSUM when Luhn passes but no brand matches.

Examples

Input: ('4242424242424242',)

Expected Output: 'VISA'

Explanation: Brand match takes precedence over the UNKNOWN fallback.

Input: ('5555555555554444',)

Expected Output: 'MASTERCARD'

Explanation: Starts with 55, 16 digits, Luhn-valid -> MASTERCARD.

Input: ('378282246310005',)

Expected Output: 'AMEX'

Explanation: 15-digit AMEX test card.

Input: ('1234567812345670',)

Expected Output: 'UNKNOWN'

Explanation: Luhn-valid but no brand pattern matches -> UNKNOWN (was INVALID_CHECKSUM in task 1).

Input: ('4242424242424241',)

Expected Output: 'INVALID_CHECKSUM'

Explanation: Fails Luhn, so INVALID_CHECKSUM regardless of prefix.

Input: ('6011111111111117',)

Expected Output: 'UNKNOWN'

Explanation: 16-digit Discover test card, Luhn-valid, starts with 60 -> matches no known brand -> UNKNOWN.

Hints

  1. This is task 1 with a single line changed: the final return becomes 'UNKNOWN' instead of 'INVALID_CHECKSUM'.
  2. INVALID_CHECKSUM is reserved exclusively for numbers that FAIL the Luhn check.
  3. A 16-digit Luhn-valid number starting with 6 (e.g. a Discover card) is UNKNOWN here, since only VISA/MASTERCARD/AMEX patterns are recognized.

Wildcard Card Counting (Analytic, Not Brute Force)

The input may contain '*' wildcards, each standing for any single digit (e.g. "****424242424242"). Return the count of possible Luhn-valid card numbers per brand, as a list of "BRAND,count" pairs (e.g. ["VISA,1", "MASTERCARD,10"]). A single pattern may be consistent with more than one brand, so report a count for every brand it could represent. Emit brands in the order VISA, MASTERCARD, AMEX, skipping any brand with a count of 0. Do NOT brute-force 10^k completions. Count analytically: - A pattern can only be a given brand if its length matches and every FIXED prefix digit is compatible with that brand's prefix rule. - A wildcard in a prefix position is constrained to the allowed prefix values (e.g. VISA's leading '*' has exactly 1 choice: '4'); multiply those choices together. - Among the remaining FREE wildcard positions, the Luhn constraint fixes one degree of freedom: the number of completions = (product of prefix-wildcard choices) * 10^(free_wildcards - 1), provided at least one wildcard is free. - If there are zero free wildcards, the count is the number of prefix-wildcard fills whose fully-determined number is Luhn-valid (1 if the single completion is valid, else 0).

Constraints

  • Input contains digits 0-9 and '*' wildcards only.
  • Number of wildcards can be large; 10^(free-1) must be computed analytically, never enumerated.
  • Counts can exceed 32-bit range; Python ints are unbounded, but Java/C++ solutions would need BigInteger for very large patterns.
  • Brands are emitted in fixed order VISA, MASTERCARD, AMEX; zero-count brands are omitted.

Examples

Input: ('****424242424242',)

Expected Output: ['VISA,100', 'MASTERCARD,50']

Explanation: 16-long, 4 leading stars. VISA: pos0 star -> 1 choice (4), 3 free -> 1*10^2=100. MASTERCARD: pos0 -> 1 (5), pos1 -> 5 (1-5), 2 free -> 5*10^1=50. AMEX needs length 15, excluded.

Input: ('4*4242424242424*',)

Expected Output: ['VISA,10']

Explanation: Fixed first digit 4 -> only VISA. 2 stars, pos0 fixed; one star is a free non-prefix position -> 10^(2-1)=10. Only the last star is free (the second char is a non-prefix position too) so f=2 -> 10.

Input: ('5*5*555555554444',)

Expected Output: ['MASTERCARD,5']

Explanation: Starts with 5 -> only MasterCard possible. pos1 star -> 5 prefix choices, 1 free star -> 5*10^0=5.

Input: ('3*1449635398431',)

Expected Output: ['AMEX,1']

Explanation: 15-long, starts with 3 -> only AMEX. pos1 star limited to {4,7} (2 choices) but it is the LAST free degree of freedom; here pos1 is a prefix position so choices=2 and free=0 -> enumerate {4,7}: only one fill is Luhn-valid -> 1.

Input: ('4242424242424242',)

Expected Output: ['VISA,1']

Explanation: No wildcards; the single fully-specified number is Luhn-valid VISA -> count 1.

Input: ('****************',)

Expected Output: ['VISA,100000000000000', 'MASTERCARD,50000000000000']

Explanation: 16 free-ish stars. VISA: 1*10^14. MASTERCARD: 1*5*10^13. Computed analytically, never enumerated.

Input: ('1234567812345670',)

Expected Output: []

Explanation: 16 digits, no wildcards, starts with 1 -> matches no brand prefix -> empty list.

Hints

  1. Treat each brand independently: first check the length matches, then check every fixed prefix digit is compatible.
  2. A wildcard inside the prefix region is NOT free: it is limited to the brand's allowed prefix values (VISA leading '*' -> 1 choice; MasterCard second '*' -> 5 choices).
  3. Luhn is a single linear (mod-10) constraint, so it removes exactly one degree of freedom: with f free wildcards the valid completions number 10^(f-1). With zero free wildcards, just enumerate the (tiny) prefix-wildcard fills and Luhn-check each.

Single-Error Card Reconstruction

An observed string ends with a trailing '?' meaning exactly one error happened to the preceding digits. The error is one of: changed digit, removed digit, added digit, or transposition of two adjacent digits (e.g. "4333220284765319?"). Enumerate every ORIGINAL card number that (a) was Luhn-valid and matched a real brand (VISA / MASTERCARD / AMEX) before the error, and (b) could have produced the observed string via exactly one such error. Invert each operation against the observed digits (drop the trailing '?'): - Changed digit: at each position, try the other 9 digits. - Removed digit (original was one longer): insert each of 10 digits at every gap. - Added digit (original was one shorter): delete each position. - Adjacent transposition: swap each adjacent pair back. Deduplicate the candidates, keep only those that are Luhn-valid AND map to a brand, and return them sorted ascending as "NUMBER,BRAND" strings.

Constraints

  • The observed string ends with a single trailing '?'.
  • Exactly one error occurred; the candidate generator inverts all four edit types and deduplicates (different edits can yield the same original).
  • Only Luhn-valid candidates that map to a real brand (VISA/MASTERCARD/AMEX) survive; UNKNOWN-shaped numbers are discarded.
  • Results are sorted ascending by the numeric string and formatted as "NUMBER,BRAND".

Examples

Input: ('4242424242424252?',)

Expected Output: ['4242424242424242,VISA', '4242424242424259,VISA', '4242424242424952,VISA', '4242424242427252,VISA', '4242424242494252,VISA', '4242424242724252,VISA', '4242424249424252,VISA', '4242424272424252,VISA', '4242424942424252,VISA', '4242427242424252,VISA', '4242494242424252,VISA', '4242724242424252,VISA', '4249424242424252,VISA', '4272424242424252,VISA', '4942424242424252,VISA']

Explanation: A near-valid 16-digit observed string; the true original 4242424242424242 is recovered by a single changed-digit inversion, alongside other VISA originals one edit away.

Input: ('371449635398431?',)

Expected Output: ['371449635398431,AMEX']

Explanation: The observed (minus '?') is already a valid 15-digit AMEX; the only branded Luhn-valid reconstruction within one edit is itself.

Input: ('424242424242424?',)

Expected Output: ['4242342424242424,VISA', '4242422424242424,VISA', '4242424024242424,VISA', '4242424214242424,VISA', '4242424242042424,VISA', '4242424242424234,VISA', '4242424242424242,VISA', '4242424242424424,VISA', '4242424242462424,VISA', '4242424248242424,VISA', '4244242424242424,VISA', '4624242424242424,VISA']

Explanation: Observed is 15 digits; inserting a digit (undoing a removed digit) reconstructs 16-digit VISA originals including 4242424242424242.

Input: ('00?',)

Expected Output: []

Explanation: Too short to ever become a valid 15/16-digit branded card via a single edit -> no reconstructions.

Hints

  1. Strip the trailing '?' first, then generate candidates for all four inverse operations into a set so duplicates collapse.
  2. Insertion (to undo a removed digit) and deletion (to undo an added digit) change the length by one - that is how a 15-digit AMEX or 16-digit VISA original can emerge from an off-by-one observed string.
  3. Re-validate each candidate with the SAME Luhn + brand rules from tasks 1-2; keep only the ones that are both Luhn-valid and brand-matched.
Last updated: Jun 25, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ 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
  • AI Coding 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

  • Assign Reviewers from Changed Files - Stripe (medium)
  • Generate Account Email Notifications - Stripe (medium)
  • Calculate Transaction Fees - Stripe (medium)
  • Build an Account Transfer Ledger - Stripe (medium)
  • Implement Validation and String Compression - Stripe (hard)