← Back to blog Stripe OA Deep Dive 2026: Card Range Obfuscation (BIN Interval Filling) Full Solution
Stripe

Stripe OA Deep Dive 2026: Card Range Obfuscation (BIN Interval Filling) Full Solution

2026-05-14

Card Range Obfuscation is the hardest "just brute force it" question in Stripe's OA history—short prompt, dense rules, byte-level hidden tests. The business context is real: BINs (Bank Identification Numbers) partition card-brand ranges, and any unmapped gap can be probed by fraudsters via card-number enumeration. Stripe needs gaps filled with "unknown" brand. This article breaks down the full solution, complexity, and the hidden-test traps that catch most candidates.

Stripe OA Overview (This Problem)

Dimension Detail
Platform HackerRank for Work
Duration 90 minutes
Questions 1 problem, 4 parts
Difficulty LeetCode Medium, very boundary-heavy
Pass threshold 12/16 hidden tests
Frequency Multiple appearances 2024-2026, variants vary BIN length (6/8)

Problem Statement

Stripe's card payment API returns BIN-range → brand mappings.

Key concepts:

Input:

Output:

Example

BIN = 424242
intervals = [
  (4242420000000000, 4242421000000000, "VISA"),
  (4242423000000000, 4242425000000000, "MASTERCARD"),
]

Expected output:

[
  (4242420000000000, 4242421000000000, "VISA"),
  (4242421000000001, 4242422999999999, "unknown"),
  (4242423000000000, 4242425000000000, "MASTERCARD"),
  (4242425000000001, 4242429999999999, "unknown"),
]

Approach

Classic interval merge + gap fill. Stripe's hidden tests scale up to 1e5 intervals, so O(n log n) is required.

Step 1: Compute the global BIN range

span      = 10 ** (16 - len(str(BIN)))
bin_start = BIN * span
bin_end   = bin_start + span - 1

BIN length can be 6 or 8—don't hard-code 10**10 or 10**12. This is the Part-3 trap.

Step 2: Sort intervals by start

Step 3: Scan intervals, inserting "unknown" on gaps

Step 4: Handle overlapping intervals (Part 4)

Stripe's Part 4 introduces overlaps. Two acceptable strategies:

  1. Reject (some versions accept this)
  2. Last-writer wins (the expected behavior in Part 4): split overlapping intervals so the later brand owns the overlapped segment

Complete Python Solution

from typing import List, Tuple

Interval = Tuple[int, int, str]

def fill_card_ranges(bin_value: int, intervals: List[Interval]) -> List[Interval]:
    bin_str = str(bin_value)
    span = 10 ** (16 - len(bin_str))
    bin_start = bin_value * span
    bin_end = bin_start + span - 1

    sorted_intervals = sorted(intervals, key=lambda x: (x[0], x[1]))
    result: List[Interval] = []
    cursor = bin_start

    for s, e, brand in sorted_intervals:
        s = max(s, bin_start)
        e = min(e, bin_end)
        if s > e:
            continue
        if s > cursor:
            result.append((cursor, s - 1, "unknown"))
        elif s < cursor:
            s = cursor
            if s > e:
                continue
        result.append((s, e, brand))
        cursor = e + 1

    if cursor <= bin_end:
        result.append((cursor, bin_end, "unknown"))

    return result

Time: O(n log n) (sort-dominated)
Space: O(n)

4 Hidden-Test Traps

Trap 1: BIN length is not fixed

Part 3 hands you an 8-digit BIN. Hard-coding 10**10 fails every time. Always derive span from len(str(bin_value)).

Trap 2: Input intervals can extend past the BIN range

Inputs sometimes have start < bin_start or end > bin_end. Clip them with max/min.

Trap 3: Adjacent intervals (off by 1, not 0)

If interval A ends at x and B starts at x+1, there's no gap—don't insert "unknown". The trick is cursor = e + 1 (not e), so adjacent intervals naturally skip gap insertion.

Trap 4: Empty input / BIN entirely uncovered

When intervals = [], output one (bin_start, bin_end, "unknown") segment. Easy to forget the post-loop cursor <= bin_end branch.

Complexity Walkthrough

With n input intervals:

Total: O(n log n) time, O(n) space.

Stripe Rubric: Maximizing Score Across 4 Parts

Part Content Weight Key
Part 1 Single BIN + non-overlapping sorted input 20% Correct splitting
Part 2 Unsorted input + gap filling 30% Sort by start
Part 3 Variable BIN length + out-of-range input 30% Dynamic span + clipping
Part 4 Overlapping intervals 20% Last-writer-wins or reject

Strategy: nail Parts 1+2 first (50%). Part 3 is the BIN-length adaptation. Skipping Part 4 still lands ~80% of total points.

FAQ

Is Card Range Obfuscation still seen in 2026 OAs?

Yes. In Q1-Q2 2026 alone, at least 6 candidates reported hitting this problem or a variant: merging same-brand contiguous ranges, or hidden tests that scale input size to 1e5.

Why does Stripe love interval problems?

Stripe's core domain (payments, subscriptions, refunds) is full of time-interval and amount-interval merging. The OA philosophy is "this is the kind of code you'll actually write here."

How do I distinguish a BIN of length 6 vs 8?

The problem statement tells you, but your code should derive it via len(str(bin_value)). Hidden tests deliberately switch BIN length to expose hardcoded constants.

Closed or half-open intervals?

Stripe uses closed intervals [start, end]. If you switch to half-open [start, end), every cursor calculation needs a +1 adjustment, and the chance of off-by-one bugs rises dramatically. Stay closed.

Is Java faster than Python here?

No. Python's sorted handles 1e5 items in well under 100ms. Grading is language-agnostic, and Python may even edge ahead on the readability axis.


Preparing for the Stripe OA?

oavoservice covers Stripe's full historical OA bank with real-time assistance: BIN Range, Brace Expansion, Subscription Notification, Shipping Cost, and more—each with hidden-case post-mortems. Our coaches include former Stripe Risk engineers who understand Stripe's grading bias toward readability + boundary handling.

Add WeChat Coding0201 to book Stripe OA coaching.

#Stripe #StripeOA #BIN #CardRange #PaymentSystem #OARealQuestions


Contact

Email: [email protected]
Telegram: @OAVOProxy