← 返回 stripe 的题目列表Chat Billing Calculation (OA)
类型:qbank
Recent high-frequency HackerRank OA. Compute each user's monthly bill across two plans: pay-as-you-go (per-token) and subscription with a token threshold. If a user has both, split usage proportionally.
Requirements
Implement calculate_monthly_billing for a chat-based AI platform that charges users by token usage. The function takes a list of chat-session records for a single month and returns a list of per-user spend strings.
Each session record is a comma-joined string: user_id, input_tokens, output_tokens, plan. A user may appear in multiple sessions during the month.
Output: one string per user in the format user_id: $xx.xx (two decimals), ordered alphabetically by user_id.
Token counts are always non-negative integers.
def calculate_monthly_billing(sessions: list[str]) -> list[str]: ...
# sessions[i] = "user_id,input_tokens,output_tokens,plan" (plan ∈ {"payg", "fixed"})
# Returns ["user_id: $xx.xx", ...] sorted alphabetically by user_id.
The problem builds up in three progressive levels, each gated by its own block of hidden test cases.
Level 1 — Pay-as-you-go (payg) (test cases 0–4)
Input tokens billed at $0.03 per 100 tokens; output tokens at $0.04 per 100 tokens.
Block billing, floor semantics: charges accrue in whole blocks of 100 tokens; any partial block is not charged. 0–99 → 0 blocks, 100–199 → 1 block, 200–299 → 2 blocks. Integer division tokens // 100 gives the block count.
A user whose sessions never reach a full block still appears in the output with $0.00.
Level 2 — Fixed plan (fixed) (test cases 5–9)
Flat fee $15.00 per month, including 40,000 input tokens and 20,000 output tokens.
Usage above the included allowance (overage) is charged at the pay-as-you-go per-block rates.
A user may have both payg and fixed sessions; keep the token buckets separate and apply the fixed allowance only to fixed-plan tokens.
Level 3 — Plan switching (proration) (test cases 10–13)
If a user has sessions on both plans, prorate the fixed-plan flat fee AND the included allowances by the user's share of fixed-plan sessions: ratio = fixed_session_count / total_session_count. Fee, input allowance, and output allowance are all multiplied by ratio before computing overage.
Token blocks are still computed per plan and costed separately.
Example: 2 payg + 2 fixed sessions → ratio = 0.5 → fee becomes $7.50, allowances become 20,000 input / 10,000 output.
Solution
Aggregate per user into separate payg / fixed token buckets plus per-plan session counts. Reuse a single per-block cost helper for both PAYG charges and fixed-plan overage.
from collections import defaultdict
INPUT_RATE = 0.03 # dollars per 100 input tokens
OUTPUT_RATE = 0.04 # dollars per 100 output tokens
MONTHLY_FEE = 15.00
INPUT_ALLOWANCE = 40_000
OUTPUT_ALLOWANCE = 20_000
def _payg_cost(input_tokens, output_tokens):
# Floor to whole 100-token blocks; partial blocks are free.
return (input_tokens // 100) * INPUT_RATE + (output_tokens // 100) * OUTPUT_RATE
def calculate_monthly_billing(sessions):
totals = defaultdict(lambda: {
"payg_input": 0, "payg_output": 0,
"fixed_input": 0, "fixed_output": 0,
"fixed_count": 0, "total_count": 0,
})
for record in sessions:
user_id, input_str, output_str, plan = record.split(",")
u = totals[user_id]
u["total_count"] += 1
if plan == "payg":
u["payg_input"] += int(input_str)
u["payg_output"] += int(output_str)
else: # "fixed"
u["fixed_input"] += int(input_str)
u["fixed_output"] += int(output_str)
u["fixed_count"] += 1
output = []
for user_id in sorted(totals):
u = totals[user_id]
cost = _payg_cost(u["payg_input"], u["payg_output"])
if u["fixed_count"] > 0:
ratio = u["fixed_count"] / u["total_count"]
prorated_input = INPUT_ALLOWANCE * ratio
prorated_output = OUTPUT_ALLOWANCE * ratio
input_overage = max(0, u["fixed_input"] - prorated_input)
output_overage = max(0, u["fixed_output"] - prorated_output)
cost += MONTHLY_FEE * ratio + _payg_cost(input_overage, output_overage)
output.append(f"{user_id}: ${cost:.2f}")
return output
Time: O(N + U log U) — N sessions, U unique users (the alphabetical sort dominates).
When a user has only fixed sessions, ratio == 1 and the math degrades exactly to the non-prorated Level 2 behavior, so earlier test cases do not regress.
Examples
["userA,100,120,payg", "userB,150,100,payg", "userB,100,130,payg"] → ["userA: $0.07", "userB: $0.14"] (each 100–199-token field bills 1 block).
Fixed plan, combined 45,000 input / 22,000 output → $15.00 fee + 50 input-overage blocks ($1.50) + 20 output-overage blocks ($0.80) = $17.30.
Mixed 2 payg + 2 fixed (ratio = 0.5): PAYG $0.14 + prorated fee $7.50 + overage $0.07 = $7.71.
Notes
The three levels are gated by contiguous hidden-test-case blocks: cases 0–4 exercise Level 1 (PAYG), 5–9 exercise Level 2 (fixed plan + overage), 10–13 exercise Level 3 (proration). A correct Level 3 implementation keeps all 14 cases green because ratio == 1 reduces it to Level 2.
HackerRank does not show the expected output for failed cases; only your output. Use print / logging to dump inputs locally.
Multiple reports note that passing all visible cases is no guarantee of success — Stripe rejects based on hidden cases and code-quality review.
One thread reports "all test cases passed and still rejected" — Stripe also reviews structure / readability of the submission.
The per-block formula is the single reused primitive: it applies to PAYG sessions and to fixed-plan overage alike. Extracting it into a helper keeps the three levels composable and avoids divergent rounding bugs.
Preparation
Drill rule-based billing problems: per-unit rate, flat fee with cap, mixed plans with proration.
Pre-write a Plan abstraction (or a shared _payg_cost helper) that exposes cost(usage) so you can compose plans cleanly.
Write code under the assumption it will be read by another engineer — keep clear names and short functions; HackerRank submissions get a code-quality review.