Find deployable slots in a recurring week from allowed and freeze windows

Read the full interview experience this question came from →

Quick Overview

A coding exercise on a recurring 10,080-minute week: combine allowed and freeze deployment windows into deployable slots, then add per-window time-zone offsets, the current time, a lead time, a minimum slot length and a cap of k results. It tests interval merging and subtraction, wrap-around at the week boundary and careful edge-case handling.

Find deployable slots in a recurring week from allowed and freeze windows

Company: Stripe

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

A deployment scheduler works on a recurring week of 10,080 minutes (7 days of 24 hours of 60 minutes). Minute `0` is the start of the week, and the same schedule repeats every week. Teams declare windows in which deployments are allowed and windows in which deployments are frozen. A minute is deployable when it lies inside at least one allowed window and inside no freeze window, and a deployable slot is a maximal run of consecutive deployable minutes. The exercise came in two parts. Part 1 takes only `(start, end, type)` windows and returns every deployable slot of the week. Part 2 adds the current UTC time, a lead time, a minimum slot length, a cap `k` on the number of slots, and a time-zone offset for each window. Implement Part 2. Part 1 is the special case `utc_now = 0`, `lead_time_minutes = 0`, `min_continuous_minutes = 1`, every `offset = 0`, and `k` at least the number of slots. ### Function Signature ```python def deployable_slots(utc_now: int, lead_time_minutes: int, min_continuous_minutes: int, k: int, windows: list[tuple[int, int, str, int]]) -> list[list[int]]: ``` ### Rules - Each window is `(start, end, type, offset)`. `start` and `end` are minutes of the week in the window's local time, and the window covers the half-open range `[start, end)`. `type` is `"allowed"` or `"freeze"`. - `offset` is the window's local time minus UTC, in minutes: a UTC-5 zone has `offset = -300` and a UTC+2 zone has `offset = 120`. In UTC the window covers `[start - offset, end - offset)`. - All times are measured on one UTC timeline in minutes, where minute `0` is the start of the current week and minute `10080` is the start of the next week. Every window occurs once per week on this timeline: at its UTC range, and at that range shifted by every multiple of 10,080 (forwards and backwards). A shifted window may therefore cross a week boundary. - Freeze wins: a minute inside any freeze occurrence is not deployable, even if an allowed occurrence also covers it. A minute covered by no allowed occurrence is not deployable. - `utc_now` is the current UTC minute of the current week. The earliest usable minute is `earliest = utc_now + lead_time_minutes`. Because the schedule repeats weekly, only the search horizon `[earliest, earliest + 10080)` is considered. - A slot is a maximal run of deployable minutes inside the search horizon, reported as `[slot_start, slot_end]` and meaning the half-open range `[slot_start, slot_end)`. Runs are cut at both ends of the horizon. Deployable minutes that are consecutive on the timeline belong to one slot, even when they come from different windows or cross a week boundary. - Keep only slots with `slot_end - slot_start >= min_continuous_minutes`, measured after cutting at the horizon. - Return the first `k` kept slots in increasing order of `slot_start`, fewer if fewer exist, and `[]` if there are none. Slots never overlap, so this order is unique. ### Constraints - `0 <= utc_now < 10080` - `0 <= lead_time_minutes <= 10^6` - `1 <= min_continuous_minutes <= 10080` - `1 <= k <= 10^4` - `0 <= len(windows) <= 10^4` - `0 <= start < end <= 10080` for every window, in its local time - `type` is exactly `"allowed"` or `"freeze"` - `-720 <= offset <= 840` - Every returned value lies between `0` and `earliest + 10080`, which is at most 1,020,159, so all values fit in a 32-bit signed integer. ### Examples **Example 1** ```text Input: utc_now = 0, lead_time_minutes = 0, min_continuous_minutes = 1, k = 10, windows = [ (600, 1200, "allowed", 0), (1000, 1080, "freeze", 0), (1150, 1500, "allowed", 0), (9900, 10080, "allowed", 0), (0, 120, "allowed", 0) ] Output: [[0, 120], [600, 1000], [1080, 1500], [9900, 10080]] ``` The freeze removes `[1000, 1080)` from the first allowed window. The overlapping allowed ranges `[1080, 1200)` and `[1150, 1500)` form one slot. The search horizon is `[0, 10080)`, so `[0, 120)` and `[9900, 10080)` are reported as two slots even though the week wraps from one to the other. **Example 2** ```text Input: utc_now = 10000, lead_time_minutes = 60, min_continuous_minutes = 90, k = 3, windows = [ (0, 240, "allowed", 0), (9960, 10080, "allowed", 0), (120, 150, "freeze", 0), (540, 720, "allowed", 120), (3000, 3030, "allowed", 0) ] Output: [[10060, 10200], [10230, 10320], [10500, 10680]] ``` `earliest = 10060`, so the horizon is `[10060, 20140)`. The allowed run that starts at `9960` continues across the week boundary into next week's `[10080, 10320)`. It is cut at `10060` and split by next week's freeze `[10200, 10230)`, leaving slots of 140 and 90 minutes. The window with `offset = 120` covers UTC `[420, 600)`, which next week is `[10500, 10680)`. Next week's `[13080, 13110)` lasts only 30 minutes and is dropped. A fourth qualifying slot, `[20040, 20140)`, exists, but `k = 3`. **Example 3** ```text Input: utc_now = 50, lead_time_minutes = 0, min_continuous_minutes = 30, k = 5, windows = [ (0, 180, "allowed", 120), (30, 60, "freeze", 120) ] Output: [[9960, 9990], [10020, 10130]] ``` With `offset = 120`, the allowed window covers UTC `[-120, 60)`, and its next weekly occurrence is `[9960, 10140)`. The freeze covers `[9990, 10020)` in that occurrence. The horizon is `[50, 10130)`. The run `[50, 60)` lasts 10 minutes and is dropped, `[9960, 9990)` lasts exactly 30 minutes and is kept, and `[10020, 10140)` is cut to `[10020, 10130)` at the end of the horizon.

Overview: A coding exercise on a recurring 10,080-minute week: combine allowed and freeze deployment windows into deployable slots, then add per-window time-zone offsets, the current time, a lead time, a minimum slot length and a cap of k results. It tests interval merging and subtraction, wrap-around at the week boundary and careful edge-case handling.

Read the full Stripe Software Engineer interview experience this question came from

|Home/Coding & Algorithms/Stripe
Stripe logo
Stripe
Sep 25, 2026
mediumSoftware EngineerOnsiteCoding & Algorithms
0
0

A deployment scheduler works on a recurring week of 10,080 minutes (7 days of 24 hours of 60 minutes). Minute 0 is the start of the week, and the same schedule repeats every week. Teams declare windows in which deployments are allowed and windows in which deployments are frozen. A minute is deployable when it lies inside at least one allowed window and inside no freeze window, and a deployable slot is a maximal run of consecutive deployable minutes.

The exercise came in two parts. Part 1 takes only (start, end, type) windows and returns every deployable slot of the week. Part 2 adds the current UTC time, a lead time, a minimum slot length, a cap k on the number of slots, and a time-zone offset for each window. Implement Part 2. Part 1 is the special case utc_now = 0, lead_time_minutes = 0, min_continuous_minutes = 1, every offset = 0, and k at least the number of slots.

Function Signature

def deployable_slots(utc_now: int, lead_time_minutes: int, min_continuous_minutes: int, k: int, windows: list[tuple[int, int, str, int]]) -> list[list[int]]:

Rules

  • Each window is (start, end, type, offset) . start and end are minutes of the week in the window's local time, and the window covers the half-open range [start, end) . type is "allowed" or "freeze" .
  • offset is the window's local time minus UTC, in minutes: a UTC-5 zone has offset = -300 and a UTC+2 zone has offset = 120 . In UTC the window covers [start - offset, end - offset) .
  • All times are measured on one UTC timeline in minutes, where minute 0 is the start of the current week and minute 10080 is the start of the next week. Every window occurs once per week on this timeline: at its UTC range, and at that range shifted by every multiple of 10,080 (forwards and backwards). A shifted window may therefore cross a week boundary.
  • Freeze wins: a minute inside any freeze occurrence is not deployable, even if an allowed occurrence also covers it. A minute covered by no allowed occurrence is not deployable.
  • utc_now is the current UTC minute of the current week. The earliest usable minute is earliest = utc_now + lead_time_minutes . Because the schedule repeats weekly, only the search horizon [earliest, earliest + 10080) is considered.
  • A slot is a maximal run of deployable minutes inside the search horizon, reported as [slot_start, slot_end] and meaning the half-open range [slot_start, slot_end) . Runs are cut at both ends of the horizon. Deployable minutes that are consecutive on the timeline belong to one slot, even when they come from different windows or cross a week boundary.
  • Keep only slots with slot_end - slot_start >= min_continuous_minutes , measured after cutting at the horizon.
  • Return the first k kept slots in increasing order of slot_start , fewer if fewer exist, and [] if there are none. Slots never overlap, so this order is unique.

Constraints

  • 0 <= utc_now < 10080
  • 0 <= lead_time_minutes <= 10^6
  • 1 <= min_continuous_minutes <= 10080
  • 1 <= k <= 10^4
  • 0 <= len(windows) <= 10^4
  • 0 <= start < end <= 10080 for every window, in its local time
  • type is exactly "allowed" or "freeze"
  • -720 <= offset <= 840
  • Every returned value lies between 0 and earliest + 10080 , which is at most 1,020,159, so all values fit in a 32-bit signed integer.

Examples

Example 1

Input:  utc_now = 0, lead_time_minutes = 0, min_continuous_minutes = 1, k = 10,
        windows = [
          (600, 1200, "allowed", 0),
          (1000, 1080, "freeze", 0),
          (1150, 1500, "allowed", 0),
          (9900, 10080, "allowed", 0),
          (0, 120, "allowed", 0)
        ]
Output: [[0, 120], [600, 1000], [1080, 1500], [9900, 10080]]

The freeze removes [1000, 1080) from the first allowed window. The overlapping allowed ranges [1080, 1200) and [1150, 1500) form one slot. The search horizon is [0, 10080), so [0, 120) and [9900, 10080) are reported as two slots even though the week wraps from one to the other.

Example 2

Input:  utc_now = 10000, lead_time_minutes = 60, min_continuous_minutes = 90, k = 3,
        windows = [
          (0, 240, "allowed", 0),
          (9960, 10080, "allowed", 0),
          (120, 150, "freeze", 0),
          (540, 720, "allowed", 120),
          (3000, 3030, "allowed", 0)
        ]
Output: [[10060, 10200], [10230, 10320], [10500, 10680]]

earliest = 10060, so the horizon is [10060, 20140). The allowed run that starts at 9960 continues across the week boundary into next week's [10080, 10320). It is cut at 10060 and split by next week's freeze [10200, 10230), leaving slots of 140 and 90 minutes. The window with offset = 120 covers UTC [420, 600), which next week is [10500, 10680). Next week's [13080, 13110) lasts only 30 minutes and is dropped. A fourth qualifying slot, [20040, 20140), exists, but k = 3.

Example 3

Input:  utc_now = 50, lead_time_minutes = 0, min_continuous_minutes = 30, k = 5,
        windows = [
          (0, 180, "allowed", 120),
          (30, 60, "freeze", 120)
        ]
Output: [[9960, 9990], [10020, 10130]]

With offset = 120, the allowed window covers UTC [-120, 60), and its next weekly occurrence is [9960, 10140). The freeze covers [9990, 10020) in that occurrence. The horizon is [50, 10130). The run [50, 60) lasts 10 minutes and is dropped, [9960, 9990) lasts exactly 30 minutes and is kept, and [10020, 10140) is cut to [10020, 10130) at the end of the horizon.

Submit Your Answer to Earn 20XP

Sign in to leave a comment

Loading comments...