Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Scenario-Based Conditional Probability and Bayes Problems

These are the conditional-probability problems that actually get asked in ML, quant, and data-science interviews, stated the way interviewers state them — as stories. Each one has a full worked solution, a sanity check, a follow-up probe, and the specific wrong answer people give. The single most useful habit in this entire document: before you compute anything, write down your events explicitly$D$ = has disease, $T$ = test positive — and then write down which conditional you were asked for. Nearly every miss in a real interview is a mis-parse of the story, not an arithmetic error, and the notation step is what prevents it. Work in natural frequencies (“imagine 10,000 people”) whenever a base rate appears; work in odds and likelihood ratios whenever evidence arrives sequentially. Every numeric answer here was verified by Monte Carlo simulation ( trials) or exhaustive enumeration; code for the trickiest ones is in the appendix.


A. Base rates and testing

Q: A disease affects 1% of the population. There’s a test for it that’s right 99% of the time when you have the disease, and wrong 5% of the time when you don’t. Your patient just tested positive. What’s the chance they actually have it?

Set up the notation.

  • = patient has the disease. .
  • = test comes back positive.
  • Sensitivity: .
  • False positive rate: (so specificity is ).
  • Asked for: . Note this is not the 0.99 the problem hands you — that number is , the other direction.

Solution.

Numerator: .

False-positive mass: .

Denominator: .

So about 16.7% — a positive result still leaves it five-to-one against the patient having the disease. The reason is that the healthy group is 99 times larger than the sick group, so even a small 5% error rate applied to that huge group produces five times more false positives than there are true positives in total.

Sanity check. Imagine 10,000 people. 100 have the disease; 99 of them test positive. 9,900 are healthy; 5% of them — 495 — test positive anyway. Total positives , of whom 99 are sick: . The table takes ten seconds and is unfalsifiable.

Follow-up: “What specificity would you need to make a positive test more likely right than wrong?” → We need , i.e. true positives exceed false positives: , so . You need a false-positive rate below 1% — specificity above 99% — just to break even. Sensitivity barely matters here; the base rate makes specificity the binding constraint.

Trap: Answering 99%. That confuses with — the prosecutor’s fallacy. A second common trap is answering 94% (), which is a meaningless product of two numbers that live on different conditioning sides.


Q: Same patient, same test. You’re suspicious, so you run the test a second time and it comes back positive again. Now what?

Set up the notation.

  • , as before. = first and second tests positive.
  • Assume conditional independence: , and likewise given . Say this out loud — it is a modeling assumption, not a fact, and the interviewer wants to hear you flag it.
  • Asked for: .

Solution. Do this in odds form, which is what makes sequential updating trivial.

Prior odds: .

Likelihood ratio of one positive: .

Each independent positive multiplies the odds by 19.8:

About 79.8%. Notice the jump from 16.7% to 79.8% off a single extra data point: the posterior odds are multiplicative in the evidence, so the second test does the same 19.8× of work as the first, but now it’s operating from a much better starting point.

Sanity check. Per 10,000: 100 sick, double-positive. 9,900 healthy, double-positive. . ✓ Also check the bound: two positives can’t get you past , and the log-odds went , a constant per test. That linearity in log-odds is the signature of correct Bayesian updating.

Follow-up: “What if the two tests aren’t independent?” → If the patient has some idiosyncrasy that cross-reacts with the assay, the second test mostly repeats the first rather than adding new information. In the limit of perfect dependence, and the second test’s LR is exactly 1 — you learn nothing and stay at 16.7%. Real duplicate tests sit between; this is why clinics confirm with a different assay, which restores approximate independence.

Trap: Recomputing from the original 1% prior and getting 16.7% again, or adding probabilities. Also: multiplying and calling it the answer.


Q: We’re designing a screening program. The condition has a prevalence of 0.4% in the target age group. Our screen catches 80% of true cases and flags 9.6% of healthy people. Leadership wants to know: of everyone we call back for follow-up, what fraction actually has the condition?

Set up the notation.

  • = has the condition, .
  • = screen flags. , .
  • Asked for: — this is exactly the precision (positive predictive value) of the screening program.

Solution.

True positives: .

False positives: .

About 3.2%. Roughly 30 women get the callback, the anxiety, and the biopsy for every one who has the condition. The program can still be worth running — the question is whether catching that one case early outweighs 29 unnecessary workups — but “3%” is the number that has to enter the cost-benefit discussion, and it is the number nobody’s intuition produces.

Sanity check. Per 100,000: 400 have it, 320 flagged. 99,600 don’t, flagged. Total flagged ; . ✓ Bound check: precision can’t exceed , and with FPR 24× the prevalence you should expect single digits before computing.

Follow-up: “How much would precision improve if we doubled sensitivity to 100%?” → Numerator becomes , denominator , precision — from 3.2% to 4.0%. Almost nothing. Now instead cut FPR from 9.6% to 1%: precision , a 7.5× improvement. At low prevalence, precision is governed almost entirely by the false-positive rate. This is the single most useful design lesson in screening.

Trap: Reporting 80% (“we catch 80% of cases, so 80% of flags are cases”). Recall and precision are different quantities and diverge violently at low base rates.


Q: Our company drug-tests employees. About 4% of the workforce actually uses. The test has 98% sensitivity and 97% specificity. HR wants to fire anyone who tests positive. Talk me out of it.

Set up the notation.

  • = employee uses, .
  • = positive test. , .
  • Asked for: .

Solution.

True positives: .

False positives: .

57.6%. A positive test is barely better than a coin flip. Out of every 100 people HR fires, about 42 are clean. Note this test is good — 98/97 is a respectable test — and the prevalence is 4%, not one-in-a-million. Even in this comfortable regime, single-test firing is indefensible.

Sanity check. Per 10,000 employees: 400 users → 392 positive. 9,600 non-users → 288 positive. . ✓ The two numbers 392 and 288 are close, which is the whole story: the small error rate on the big group nearly matches the high hit rate on the small group.

Follow-up: “So retest the positives. What then?” → Odds form. Prior odds . . After one positive: odds , ✓. After two independent positives: odds , . Two positives gets you to 97.8%, which is a defensible threshold. The policy fix is “confirm before acting,” and it costs one extra test on 6.8% of the workforce.

Trap: Averaging sensitivity and specificity into “97.5% accurate, so 97.5% of positives are users.” Accuracy is a weighted average over both classes and tells you nothing directly about precision.


Q: 60% of the mail hitting our servers is spam. The word “free” shows up in 20% of spam messages and 2% of legitimate ones. A message contains “free.” How confident should the filter be?

Set up the notation.

  • = spam, , .
  • = message contains “free”. , .
  • Asked for: .

Solution.

93.75%. Contrast this with the medical cases: here the base rate helps. The prior odds are already in favor of spam, and the likelihood ratio is , giving posterior odds . When the prior is favorable, even modest evidence produces a confident posterior — the same LR of 10 applied to a 1-in-1000 prior would only reach 1%.

Sanity check. Per 10,000 messages: 6,000 spam, 1,200 contain “free”. 4,000 ham, 80 contain “free”. . ✓

Follow-up: “Now the message also contains ‘viagra’, present in 30% of spam and 0.1% of ham. Combine them.” → Naive Bayes assumes conditional independence given the class. Posterior odds , so . The independence assumption is clearly false — spammy words co-occur — so this overstates confidence. Naive Bayes is famously well-calibrated in ranking and badly calibrated in probability for exactly this reason, and the fix is to threshold on the score rather than trust the number.

Trap: Computing and reporting that, or reporting . Also, forgetting that “contains free” is evidence and treating as the answer.


Q: We built a fraud model. Fraud is 0.1% of transactions. In offline eval it catches 95% of fraud with a 1% false-positive rate. The team is thrilled. What will the ops team see?

Set up the notation.

  • = transaction is fraudulent, .
  • = model alerts. (recall), .
  • Asked for: = precision, which is what the human reviewing the queue experiences.

Solution.

True positives: .

False positives: .

8.7% precision. The reviewer clears about 11 transactions to find one fraud. Also note the alert volume: of all traffic gets flagged, which at 10M transactions/day is 109,400 alerts — an ops impossibility. The model’s 95%/1% looks excellent on a balanced test set and is unshippable at the true base rate.

Sanity check. Per 1,000,000 transactions: 1,000 fraud → 950 alerts. 999,000 legit → 9,990 alerts. . ✓ Rule of thumb worth memorizing: precision when FPR dominates, here , close to the true 0.087.

Follow-up: “What FPR do we need for 50% precision?” → Set true positives false positives: , so , about 0.095% — a 10.5× reduction. To get 90% precision you’d need , a 94× reduction. This is why fraud teams live on the far-left tail of the ROC curve, where the usual AUC summary is nearly uninformative, and why they report precision-recall curves and precision@k instead.

Trap: Reporting recall (95%) as if it answered the question, or assuming a 1% FPR means “only 1% of alerts are wrong.”


Q: Security tooling flags suspicious logins. Roughly 1 in 10,000 login attempts is actually malicious. The detector catches 99% of malicious logins and flags 0.5% of legitimate ones. The SOC analyst gets a page. Should they wake anyone up?

Set up the notation.

  • = login is malicious, .
  • = detector fires. , .
  • Asked for: .

Solution.

True positives: .

False positives: .

1.94% — about 1 in 51 pages is real. This is the arithmetic of alert fatigue: analysts learn, correctly, that pages are almost always noise, and then miss the real one. The detector isn’t broken; it’s being asked to find a needle in a haystack that is 10,000× larger than the needle.

Sanity check. Per 10,000,000 logins: 1,000 malicious → 990 alerts. 9,999,000 legit → 49,995 alerts. . ✓ Fifty thousand alerts to find 990 attacks.

Follow-up: “How do you fix it without touching the model?” → Raise the prior, not the threshold. Condition on context that shifts upward before the detector is consulted: new geography, impossible travel, first-time device, off-hours, privileged account. If you only run the detector on the 1% of logins where , prior odds go from to , and with the precision becomes … precisely: . Same detector, 34× the precision. Segmenting the population is almost always cheaper than improving the classifier.

Trap: “0.5% false positive rate means 99.5% of alerts are real.” The FPR is conditioned on the (enormous) benign class; it says nothing about the composition of the alert queue.


Q: A candidate tells me their model has 99% accuracy on a medical dataset. I’m not impressed. Why not, and what should I ask them?

Set up the notation.

  • = patient has the condition; prevalence .
  • = model prediction.
  • Accuracy .

Solution. First, the null model. Predict always: sensitivity 0, specificity 1, so

A model that has learned literally nothing scores 99%. So 99% accuracy carries zero information until compared against the 99% baseline.

Second, suppose the model is genuinely doing something — say it has 50% sensitivity — and still reports 99% accuracy. Solve for specificity:

so . Precision:

So the honest description of this “99% accurate” model is: it misses half of all sick patients, and half of its alarms are false. Both those sentences are informative; “99% accuracy” is not.

Sanity check. Natural frequencies make it a one-liner. Per 10,000: 100 sick, 9,900 healthy. 99% accuracy = 100 total errors. Sensitivity 50% → 50 false negatives, so the other 50 errors are false positives. Predicted-positive = 50 TP + 50 FP → precision exactly 0.5, and recall exactly 0.5. The whole confusion matrix falls out of “100 errors, split 50/50.”

Follow-up: “What should I ask instead?” → Ask for the confusion matrix at the operating threshold, plus (a) the base rate in the eval set and whether it matches production, (b) recall and precision separately, (c) AUC-PR rather than AUC-ROC (ROC is insensitive to class imbalance because both its axes are normalized within-class), and (d) the null-model score for comparison. A useful single number is lift or balanced accuracy: here balanced accuracy , which correctly reads as “mediocre” where 99% read as “excellent.”

Trap: Accepting accuracy at all on imbalanced data — and its cousin, tuning a model on accuracy and watching it converge to the majority-class predictor.


B. The famous ones, done properly

Q: Three doors, a car behind one, goats behind the other two. You pick door 1. The host, who knows where the car is, opens door 3 to reveal a goat and offers you the switch. Do you switch? And I want to know why the answer is what it is.

Set up the notation. The protocol matters more than the arithmetic, so state it as assumptions:

  • = car is behind door ; .
  • You pick door 1.
  • = host opens door . Host protocol: the host (i) always opens a door, (ii) never opens your door, (iii) never opens the car door, (iv) picks uniformly at random when both remaining doors have goats.
  • Asked for: versus .

Solution. The likelihoods of “host opens 3” under each hypothesis:

  • — car is behind your door, both 2 and 3 are goats, host flips a coin.
  • — host is forced; he can’t open your door 1 and can’t open the car door 2.
  • — he never opens the car.

Switch: versus . The why: the host’s action is informative because it is constrained. When the car is behind door 2, the host has no choice — his opening of door 3 is a deterministic consequence, likelihood 1. When the car is behind your door, opening 3 was a coin flip, likelihood 1/2. That likelihood ratio of against your door is the entire content of the puzzle. The host is leaking information about where the car isn’t, and he can only leak it about doors you didn’t pick.

Sanity check. Your initial pick is wrong with probability 2/3. Whenever it’s wrong, the host is forced to reveal the only other goat, so the remaining door is the car — switching wins. Whenever your pick is right (prob 1/3), switching loses. So switching wins exactly when you were initially wrong: . ✓ Extend to 100 doors and have the host open 98 goats: switching wins 99/100, and nobody’s intuition resists that version.

Follow-up: “Now the host doesn’t know where the car is — he opens one of the two doors you didn’t pick, uniformly at random, and it happens to show a goat. Switch?” → Recompute the likelihoods under the new protocol: , , (he might have revealed the car; we’re conditioning on the event that he didn’t). Now , and

It’s 50-50 and switching doesn’t matter. Identical observed data — door 3, a goat — different posterior, because the process that generated the observation changed. This is the deepest point in the problem: likelihoods are properties of the data-generating mechanism, not of the data. It’s the same reason optional stopping breaks frequentist inference and why you must model your missing-data mechanism.

Trap: “Two doors left, so it’s 50-50.” This treats the host’s choice as uninformative, which is only correct under the random-host protocol. The other trap is stating without being able to name the protocol assumptions — interviewers ask this one precisely to see whether you memorized an answer or understand conditioning.


Q: A family has two children. (a) You learn at least one is a boy. What’s the probability both are boys? (b) You learn the older one is a boy. Now what? And explain why these aren’t the same question.

Set up the notation. Sample space of (older, younger), each equally likely at probability 1/4:

writing the older child first. Assume boys and girls equally likely and independent across children.

  • (a) Event at least one boy, .
  • (b) Event older is a boy, .
  • Target event , .

Solution.

(a)

(b)

Why they differ: conditioning is restriction of the sample space, and the two pieces of information restrict it differently. “At least one boy” eliminates only , leaving three equally likely outcomes of which one is . “The older is a boy” eliminates both and , leaving two outcomes of which one is . The second statement is strictly more information: it tells you which child is the boy, which decouples the two children and leaves the other one a free coin flip. The first statement is a joint constraint on the pair and cannot be decomposed that way.

Sanity check. Imagine 4,000 two-child families: 1,000 each of . (a) 3,000 have at least one boy; 1,000 of those are → 1/3. ✓ (b) 2,000 have an older boy; 1,000 are → 1/2. ✓ Both fall straight out of the table, which is why you draw the table.

Follow-up: “You meet one of the two children and she’s a girl. Probability both are girls?” → This depends on the sampling mechanism, and that’s the point. If you met a uniformly random one of the two children, then , , . So — the random-child version, which behaves like (b), not like (a). “At least one is a girl” gives 1/3; “a randomly met child is a girl” gives 1/2. Same words in casual English, different mechanisms.

Trap: Answering 1/2 to (a) by reasoning “the other child is an independent coin flip.” There is no “other child” until you specify which one is the boy — and “at least one” deliberately refuses to specify.


Q: A family has two children. At least one is a boy born on a Tuesday. What’s the probability both are boys?

Set up the notation. Each child is a (sex, birth-day) pair, uniform over equally likely types, independent across children. The sample space has equally likely ordered outcomes.

  • = at least one child is a boy-born-Tuesday (call this type ).
  • = both children are boys.
  • Asked for: .

Solution. Count outcomes in by complement. , so

Now count : both boys, at least one Tuesday. Both-boys outcomes: each child is (boy, day), . Among these, at least one Tuesday: .

13/27, which sits between the 1/3 of “at least one boy” and the 1/2 of “the older is a boy.” The day-of-week detail acts as a partial identifier: the rarer the qualifying attribute, the more it pins down which child is the boy, and the closer you get to 1/2. The mechanism is visible in the counting — the double-counting term. Of the 27 outcomes in , exactly one has both children ; the asymmetry between “” and a naive “” is exactly the overlap that makes the answer rather than .

Sanity check. Generalize: if the attribute has probability of appearing in a given child, then . With : . Take the limits — if the attribute is vacuous (, i.e. just “a boy”), the formula collapses to ; as the attribute becomes vanishingly rare (), it approaches . is just below , consistent with Tuesday being fairly rare (1 in 7). ✓ Monte Carlo over 8M families gives 0.4810.

Follow-up: “At least one is a boy born on a Tuesday in a leap year, at 3:47pm. Now?” → As the qualifying description becomes unique, . Formally, with attribute probability per child, — cleaner to just recompute: let be the chance a child is a boy-with-attribute and note , . As : … numerically at : , , ratio . So yes, .

Trap: Answering 1/3 (“Tuesday is irrelevant, it’s just a boy”). The day is not irrelevant because it changes how the conditioning event partitions the pair. The reverse trap is answering 1/2 by over-identifying — the Tuesday boy still might be either child.


Q: Three boxes. One has two gold coins, one has two silver, one has one of each. You pick a box at random, pull out a coin without looking at the rest, and it’s gold. What’s the probability the other coin in that box is also gold?

Set up the notation.

  • Boxes: , , , each chosen with probability .
  • = the coin drawn is gold.
  • Asked for: .
  • Likelihoods: , , .

Solution.

2/3. The intuition: drawing a gold coin is twice as likely from the box as from the box, so it’s evidence favoring by a likelihood ratio of 2. It’s the same structure as Monty Hall, which is not a coincidence — both are “an observation that a constrained mechanism was more likely to produce under one hypothesis.”

Sanity check. Label the six coins. Three are gold: two of them live in the box, one in the box. Conditioning on “I drew a gold coin” makes each of the three gold coins equally likely to be the one I hold, and two of the three have a gold sibling. . ✓ This coin-level (rather than box-level) accounting is the fastest correct route.

Follow-up: “Same setup, but you’re told only that the box you picked contains at least one gold coin. Now?” → Different information. This eliminates and leaves and equally likely: . Compare with the draw version’s . Observing a random draw is stronger evidence than being told a fact about the box, because the draw is length-biased toward boxes with more gold. Recognizing when your data is a biased sample versus a logical constraint is the transferable skill here.

Trap: “The box is out, so it’s or , 50-50.” That’s the answer to the follow-up, not to the question asked. The draw carries extra information beyond “this box has some gold.”


Q: Three prisoners, A, B, and C. One will be pardoned, chosen uniformly at random; the other two are executed. The warden knows who. Prisoner A asks the warden to name one of the other two who will be executed. The warden says “B will be executed.” A is now delighted — he thinks his chances went from 1/3 to 1/2. Is he right?

Set up the notation.

  • = that prisoner is pardoned, each probability .
  • = warden says “B will be executed.”
  • Warden protocol: he always names one of the two prisoners other than A, always names someone who will actually be executed, and when both B and C are doomed (i.e. A is pardoned) he picks between them uniformly at random. State this — as in Monty Hall, the protocol is the problem.
  • Asked for: .

Solution. Likelihoods:

  • (both B and C doomed, warden flips a coin).
  • (he won’t name the pardoned man).
  • (forced: he must name B).

A’s probability is unchanged at 1/3; C’s has doubled to 2/3. A is wrong to be delighted. The warden was always going to name one of B or C, so the fact that he named someone conveys nothing about A — the event “warden names an unlucky non-A prisoner” has probability 1 regardless of who’s pardoned. All the information flows to C.

Sanity check. Run 6,000 trials of the protocol. A pardoned 2,000 times → warden says B 1,000 times, C 1,000 times. B pardoned 2,000 times → warden must say C, 2,000 times. C pardoned 2,000 times → warden must say B, 2,000 times. Warden says B in cases; A is pardoned in 1,000 of them → . ✓ And C is pardoned in 2,000 of them → . ✓

Follow-up: “What if the warden is known to prefer naming B whenever he has a choice?” → Then instead of . Recompute: , so and . Now hearing “B” is good news for A. And if the warden had said “C” under this biased protocol, (only when B is pardoned… careful: , , ), giving — A would know he’s doomed. The warden’s tie-breaking rule, an apparently irrelevant detail, entirely determines what A learns.

Trap: A’s own reasoning — “one of B, C is eliminated, so it’s between me and the other one, 1/2.” Identical error to the 50-50 Monty Hall answer.


Q: Two envelopes. One contains twice as much money as the other. You pick one, open it, and find $20. You’re offered a swap. Your colleague argues: “The other envelope has either $10 or $40, equally likely, so its expected value is $25 > $20 — always swap.” Where’s the flaw?

Set up the notation. The flaw is that “equally likely” was assumed, not derived — it requires a prior over the pair, and the paradox dissolves once you write one down. So write one down.

  • Let the pair be with probability , or with probability . (Any proper prior works; this one is minimal.)
  • You are handed one of the two envelopes uniformly at random. = amount you see, = amount in the other envelope.
  • Asked for: , and separately unconditionally.

Solution. Enumerate the four equally likely states:

pairyou hold
small1020
large2010
small2040
large4020

Condition on : two states, each probability , so each has conditional probability .

So under this prior the colleague’s arithmetic is right at $20 — swapping is genuinely favorable. But now check the other cases:

  • : pair must be , so with certainty. , gain .
  • : pair must be , so . , gain .

Unconditional expected gain from always swapping:

Exactly $0. Swapping is a wash overall, as symmetry demands ( and are exchangeable). The flaw in the paradox is that the colleague applies “ is or with probability 1/2 each” at every value of simultaneously. No proper probability distribution permits that: it would require to be constant over an unbounded geometric ladder , which cannot be normalized. The improper “uniform over all scales” prior is the error, not the arithmetic.

Sanity check. Symmetry: since you picked your envelope at random, by construction, so no matter what the prior is — you can assert this before computing anything. The conditional gains must therefore average to zero, which is why the favorable-looking and at must be paid for by the at . Monte Carlo over 20M trials: mean gain . ✓

Follow-up: “Is there ever a case where you should always swap?” → Under any proper prior, no: always. But conditionally, swapping can be right for a range of observed values. With this prior, swap if you see $10 or $20, keep if you see $40. The general rule: swap when , which happens when is small relative to your prior. If you had a real prior over the amounts — say, a plausible bound on how much money an experimenter would put in an envelope — you’d compute a threshold and swap below it. The paradox only bites when you refuse to have a prior.

Trap: Concluding “always swap” and then noticing you could swap forever (a money pump), which should have been the tell. The other trap is the reverse — declaring the colleague’s $25 wrong. It isn’t wrong at $20 under a stated prior; what’s wrong is claiming it at every value.


Q: Sleeping Beauty. She’s put to sleep Sunday. A fair coin is flipped. If heads, she’s woken once, on Monday. If tails, she’s woken twice, Monday and Tuesday, with her memory of Monday erased. She wakes up. What probability should she assign to heads? I don’t want you to just pick a side — I want you to explain the disagreement.

Set up the notation. The disagreement is entirely about what the sample space is, so the honest move is to write down both.

  • = coin landed heads. before the experiment.
  • Halfer sample space: experimental runs. , each . The event “Beauty is awake at some point” has probability 1 under both, so it’s uninformative.
  • Thirder sample space: awakening episodes. . Heads runs generate one episode; tails runs generate two.

Solution — the halfer argument. Let = “Beauty is awake and being asked.” Then : the experiment guarantees she wakes either way. So the likelihood ratio is 1 and

Waking up is not evidence, because it was certain. She knew on Sunday that she would wake; observing a foregone conclusion cannot shift a posterior.

Solution — the thirder argument. Weight by episode. Over runs, expect heads runs producing episodes, and tails runs producing episodes. Total episodes , of which are heads episodes:

Equivalently: the three episodes are indistinguishable from the inside, and a self-locating agent should spread credence uniformly over indistinguishable episodes — giving to heads.

Where the disagreement actually lives. Both computations are correct for their own sample space, and simulation confirms both simultaneously: over 2M runs, the fraction of runs that were heads is , and the fraction of awakenings that occur in heads runs is . Neither number is wrong. The dispute is over which one answers “what probability should she assign,” and that is a question about the reference class for self-locating belief, not about the probability calculus. A useful reframing: if Beauty is paid for each correct guess she makes (per awakening), she should bet as a thirder, because tails runs give her two chances to collect. If she’s paid once per run for having called it correctly, she’s indifferent at 1/2. The betting structure disambiguates the question; the coin never does.

Sanity check. Amplify the asymmetry: tails means 1,000 awakenings. Thirder credence in heads becomes ; halfer stays at . Under repeated per-awakening betting, the halfer loses badly — she’d take even-money bets on heads while only 1 in 1,001 awakenings is a heads awakening. That doesn’t logically refute halfism (the halfer replies that per-awakening betting changes the payoff structure, not the credence), but it shows which position is operationally load-bearing.

Follow-up: “She’s told it’s Monday. Now what?” → Both camps converge, but from different places. Thirder: the episode set restricts to , previously each, so . Halfer: from , learning “Monday” is evidence for heads under some formalizations (heads guarantees Monday; tails makes Monday one of two days), giving — so halfers split here too. The follow-up is where interviewers find out whether you actually understand the structure or memorized “the answer is 1/3.”

Trap: Asserting one answer confidently as the answer. This is a live disagreement among people who understand probability perfectly well; the interviewer is testing whether you can identify that the ambiguity is in the sample space. The other trap is calling it “just semantics” — it isn’t, because the two positions give different betting advice under different payoff structures, and you have to specify which.


Q: How many people do you need in a room before there’s a better-than-even chance two of them share a birthday? And then: how does this bound the number of items I can hash into a 64-bit space?

Set up the notation.

  • equally likely birthdays, people, independent.
  • = at least two people share a birthday. Compute via the complement = all birthdays distinct.

Solution.

For :

So 23 people. For : . For : .

The general result. Use :

Set this to : , so

Check: , and the true answer is 23. ✓ The scaling is , not — that is the whole insight, and it’s why collisions arrive far sooner than intuition says.

Hash-collision application. For a -bit hash, and the 50% collision point is at :

hash width50%-collision
32-bit
64-bit
128-bit

So a 64-bit hash collides with probability 1/2 at about 5 billion items — well within the range of a large production system. That is why content-addressed stores use 128 bits or more, and why “birthday bound” means “effective security is half the bit-width.”

Sanity check. The number of pairs among people is , each colliding with probability . Expected collisions ; setting this to (Poisson: ) gives , so , . ✓ Two independent derivations landing on 23 is the sanity check. Monte Carlo (1M trials): 0.5078 at , 0.9701 at . ✓

Follow-up: “For a small collision probability , how many items can I hash?” → For small , , so . For a 64-bit hash and : . Six million items already buys you a one-in-a-million collision chance. Note the shape: scales as , so demanding 100× safer only costs you 10× in capacity.

Trap: Answering 183 (), which answers a different question — how many people until someone shares your specific birthday with probability (that’s actually , from ). The birthday problem counts pairs, of which there are , not .


C. Urns, draws, and coins

Q: An urn has 5 red and 3 blue balls. You draw three without replacement. What’s the probability all three are red? And what’s the probability the third is red given the first two were?

Set up the notation.

  • = ball on draw is red, for . Sampling is without replacement, so the are dependent.
  • Asked for: and .

Solution. Chain rule, tracking the urn’s composition:

And directly, : after two reds are gone the urn holds 3 red and 3 blue, so it’s a fair coin. Conditioning has driven this from down to each red you observe makes the next red less likely, because without-replacement sampling induces negative correlation between draws.

Sanity check. Combinatorially: . ✓ Two routes (sequential conditioning, unordered counting) agreeing is the check you want, and it also demonstrates that order doesn’t matter for the unordered event. Monte Carlo (4M): 0.1788 and 0.5007. ✓

Follow-up: “Now with replacement. Same two questions.” → With replacement the draws are i.i.d. with . So , and — the conditioning does nothing, by independence. Note : with replacement you keep the favorable balls available, so runs of the same color are more likely. The gap vs is the finite-population correction in miniature.

Trap: Using for the without-replacement case, or — subtler — computing instead of . Unconditionally by symmetry (see the next problems); conditionally it’s .


Q: A bag holds 10 coins. Nine are fair; one has heads on both sides. You grab a coin at random and flip it five times. Five heads. What’s the probability you’re holding the two-headed coin?

Set up the notation.

  • = coin is fair, . = coin is two-headed, .
  • = five heads in five flips.
  • Likelihoods: , .
  • Asked for: .

Solution.

32/41 ≈ 78%. The odds form is cleaner and worth internalizing: prior odds , likelihood ratio , posterior odds , so . Every additional head doubles the posterior odds, which is why five flips are enough to overturn a 9-to-1 prior.

Sanity check. Per 320 experiments: 32 use the two-headed coin, all 32 give five heads. 288 use a fair coin, give five heads. . ✓ (Choosing 320 = as the denominator is the trick that keeps everything integral.)

Follow-up: “How many heads in a row before you’d be 99% sure?” → Posterior odds after heads . Need : , so , i.e. flips. Check: odds , . ✓ Also worth noting the converse: a single tail takes the posterior to exactly 0, since . Evidence that is impossible under a hypothesis kills it outright — which is why real models never assign probability exactly zero.

Trap: Answering (ignoring the evidence) or (reporting a likelihood as a posterior). Also, forgetting that the fair coin can produce five heads and treating as proof of .


Q: I have two coins: a fair one, and one that comes up heads 75% of the time. I pick one at random and flip it ten times, getting 8 heads and 2 tails. Which coin do I have?

Set up the notation.

  • = biased coin (), = fair coin (). .
  • = observed 8 heads in 10 flips (a specific count, not a specific sequence — the factor is common to both hypotheses and cancels, so we can drop it).
  • Asked for: .

Solution.

Likelihood ratio . With equal priors, posterior odds :

86.5% for the biased coin. Note that 8/10 heads is the maximum-likelihood point for , closer to 0.75 than to 0.5 — yet the posterior is only 86.5%, not 99%. Ten flips is simply not much data; the fair coin produces 8+ heads about 5.5% of the time.

Sanity check. Compute the two probabilities directly with the binomial coefficient: . . . Ratio . ✓ Same answer with the coefficient included, confirming it cancels. Monte Carlo (6M): 0.8653. ✓

Follow-up: “How many flips to be 95% sure, if the coin really is biased?” → Per flip, the expected log-likelihood ratio under the biased coin (the KL divergence) is We need log-odds , so flips on average. That’s the right way to think about sample size for hypothesis discrimination: information accumulates linearly in at a rate given by the KL divergence between the hypotheses, so easily-confused hypotheses (small KL) need many more samples.

Trap: Reporting the MLE (“, so it’s the biased coin”) without a posterior, or reporting the likelihood as the probability. Also: forgetting the priors are equal by assumption here — if the fair coin were 100× more common the answer would flip to .


Q: An urn has 3 red and 2 blue balls. You draw two without replacement. I tell you the second ball was red. What’s the probability the first was red?

Set up the notation.

  • = first, second ball red.
  • Asked for: — note the conditioning runs backwards in time, which is the whole point.

Solution. First get . By the law of total probability:

Joint: .

1/2 — and notice it equals . That’s not a coincidence: since by exchangeability, Bayes’ rule gives . Conditional probability doesn’t care about time order. There’s nothing causally strange about the second draw “informing” the first — you’re just describing a symmetric joint distribution, and information flows in whichever direction you condition.

Sanity check. Enumerate all equally likely ordered draws. Reds are , blues . Pairs with a red second: second is one of 3 reds (3 choices) × first is any of the other 4 balls = 12 outcomes. Of those, first is red in . . ✓ Also note — the exchangeability that makes the symmetry work. Monte Carlo (4M): 0.4995. ✓

Follow-up: “What’s the probability the last ball drawn from the full urn is red, if you draw all five?”, by exchangeability — every position in a uniformly random permutation is equally likely to hold each ball, so position 5 is as likely to be red as position 1. No conditioning needed and no computation needed. This is the trick behind a large family of problems (“what’s the chance the last card is the ace of spades,” “does the first player have an advantage in a drawing game”): a random permutation is symmetric under relabeling of positions, so any marginal position has the same distribution.

Trap: Saying “the first draw happened before the second, so the second can’t tell you anything about it,” and answering . Time asymmetry and probabilistic asymmetry are unrelated. The opposite trap is over-thinking it and computing from a depleted-urn argument that happens to give the right number for the wrong reason.


Q: Pólya’s urn: one red ball, one blue ball. You draw a ball, note its color, then put it back along with an extra ball of the same color. Repeat. What’s the probability the first two draws are both red? What’s the probability the third draw is red?

Set up the notation.

  • = draw is red. The urn reinforces: after each draw the drawn color becomes more likely, so the are positively correlated (the opposite of without-replacement sampling).
  • Start: 1 red, 1 blue, 2 total.

Solution.

Now , summing over the four paths (urn always has 4 balls before draw 3):

  • :
  • :
  • :
  • :

, unchanged from . The urn is exchangeable: every draw has marginal probability red, even though the draws are strongly dependent. Reinforcement changes the correlation structure without changing the marginals. Note , confirming positive correlation.

Sanity check. After draws, the fraction of red balls converges to a random variable (this urn’s de Finetti mixing measure is ). So the process is equivalent to: draw once, then flip a -coin forever. Under that description, ✓, ✓, , and ✓. All four numbers reproduced from one clean idea — this is the sanity check that shows you understand the object. Monte Carlo (400k): 0.3341, 0.5012, 0.7503. ✓

Follow-up: “So what’s ?”. Check directly: by telescoping. ✓ Compare with i.i.d. fair coins, : for , Pólya gives versus — nearly 100× more likely. Reinforcement makes long runs common, which is exactly why Pólya urns (and their cousin the Chinese Restaurant Process) model rich-get-richer phenomena: preferential attachment, word frequencies, contagion.

Trap: Assuming because “the urn drifts.” It drifts, but symmetrically — it’s as likely to drift blue as red. The other trap is assuming exchangeability implies independence; here the draws are exchangeable and highly dependent.


Q: A batch of 100 items contains 10 defective. You sample 10 items. Compare sampling with and without replacement: expected number of defectives found, the variance, and the probability of finding none.

Set up the notation.

  • , defective, sampled. = number of defectives in the sample.
  • With replacement: .
  • Without replacement: .

Solution.

Expectation — identical. Write where indicates the -th pick is defective. In both schemes by symmetry (for without replacement, exchangeability again). Linearity of expectation doesn’t care about dependence:

Variance — different.

The factor is the finite population correction. Without replacement is less variable because the draws are negatively correlated — drawing a defective makes the next one less likely, which damps fluctuations.

Probability of none.

Without replacement is less likely to miss all defectives (0.3305 vs 0.3487): once you’ve drawn clean items, the remaining pool is relatively richer in defectives, so a clean sweep is harder to sustain. Sampling without replacement is a slightly better inspection scheme.

Sanity check. As with fixed, the correction and hypergeometric → binomial. Here , so the correction is — a 9% variance reduction, matching the rule of thumb “ignore the FPC when you sample under 5% of the population.” Monte Carlo (3M draws without replacement): , , . ✓

Follow-up: “I want 95% confidence of catching at least one defective. How big a sample?” → Without replacement, the probability of missing all 10 defectives in a sample of is , and we need it . Computing: , , . So . With replacement: , so . Without replacement needs a smaller sample for the same guarantee — another reason acceptance sampling is done without replacement.

Trap: Assuming the expectations differ because the schemes differ. They don’t — linearity of expectation is indifferent to dependence, and this is the single most useful fact in the whole variance/expectation toolkit. The reverse trap is assuming the variances are the same.


Q: You flip a fair coin repeatedly. On average, how many flips until you first see HH? What about HT? Most people say they’re the same. They aren’t.

Set up the notation.

  • Fair coin, i.i.d. flips. = index of the flip completing the first HH; likewise.
  • Asked for: and .

Solution — HT. To get HT you must first get an H, then wait for the first T after it.

  • Expected flips to see the first H: geometric with , so .
  • From there, expected flips to see the first T: also .

Solution — HH. Markov chain with states (no progress / just saw T), (just saw one H), (done). Let , .

From the first: . Substitute into the second: , so , , and .

Why the asymmetry. It’s about how a failure sets you back. In state (just saw H) waiting for HT, a “failure” is another H — but that H is itself a fresh usable H, so you lose nothing: you’re still one step from done. Waiting for HH, a failure is a T, which destroys your progress entirely and sends you back to scratch. Patterns that can overlap with themselves take longer to appear. HH overlaps itself (the H that ends one attempt starts the next); HT does not.

Sanity check. Both patterns have probability per position, so a naive “expected wait ” gives 4 for both — correct for HT, wrong for HH. Why? Because is the mean gap between occurrences in a long run (renewal theory), and that is 4 for both. But HH occurrences cluster (HHH contains two HHs at consecutive positions), so the mean gap of 4 is made up of many short gaps and some long ones; the wait from a cold start is longer than the average gap. HT occurrences can’t cluster, so its cold-start wait equals its mean gap. Conway’s leading-number algorithm gives the general answer: over overlaps; for HH the self-overlap contributes , for HT only . ✓ Monte Carlo (400k): 5.989 and 3.996. ✓

Follow-up: “In a race, what’s the probability HH appears before HT?”Exactly 1/2, and the argument is a one-liner. Both patterns require an H first, so nothing can happen until the first H arrives (it does, with probability 1). The very next flip decides the race outright: if it’s H, HH is complete; if it’s T, HT is complete. One fair flip, so each. The striking consequence: HH takes 50% longer to arrive on average (6 vs 4) yet wins the head-to-head race exactly half the time. The extra waiting time for HH comes from its variance, not from any systematic disadvantage — HH’s distribution has a heavier right tail (repeated near-misses that get reset), which inflates the mean without shifting the median or the race outcome. Simulation over 2M races: 0.4998. ✓

Trap: “Both patterns have probability 1/4 per position, so both waits are 4.” The per-position probability determines a pattern’s long-run frequency, not its cold-start expected wait; the two coincide only for non-self-overlapping patterns. The second trap is inferring from that HT wins the race more often — it doesn’t. Expected waiting times do not order race probabilities, and Penney’s game exploits exactly this: for any pattern your opponent picks (length ), you can pick one that beats it, and the winning choice is not the one with the shorter expected wait.


Q: You have a coin you know is biased, but you don’t know the bias. Using only this coin, generate a perfectly fair coin flip. Then tell me the cost.

Set up the notation.

  • Coin has unknown , flips i.i.d.
  • Goal: output a bit with exactly, for every .

Solution (von Neumann, 1951). Flip the coin twice:

  • HT → output 1
  • TH → output 0
  • HH or TT → discard both and start over.

Correctness: and . These are exactly equal for every , so conditioned on the pair being one of the two accepted outcomes,

The bias cancels because the two orderings of one H and one T have identical probability — a symmetry argument that requires no knowledge of at all. That is the beautiful part: the procedure is distribution-free.

The cost. . Number of pairs needed is geometric with that success probability, so

For : flips per bit. For : flips per bit. For : flips per bit. The method is exact but wasteful, and it degrades as the coin gets more extreme.

Sanity check. Test the extremes: at or the acceptance probability and the cost , correctly reflecting that a nearly-deterministic coin carries almost no entropy. Compare against the information-theoretic floor: a coin has entropy bits/flip, so an optimal extractor needs flips per fair bit. Von Neumann uses 4.76 — about 4.2× worse than optimal, the price of simplicity. Monte Carlo (, 2M pairs): output frequency 0.4996, cost 4.759 flips/bit. ✓

Follow-up: “Can you do better?” → Yes. Von Neumann discards HH and TT, but those outcomes carry information too. Advanced multi-level extraction (Peres, 1992) recycles them: feed the sequence of discarded-pair types (HH vs TT) into the same procedure recursively, and also feed the sequence of accepted-pair positions. Peres’s iterated construction is asymptotically optimal, extracting bits per flip. A practical middle ground: run von Neumann on non-overlapping pairs as usual, then run it again on the subsequence of discarded pairs (treating HH as “1” and TT as “0” — these are unequally likely, at and , so von Neumann applies to them too), and emit both bit streams. That second pass alone recovers a substantial fraction of the waste at no extra flips. In production you’d use a cryptographic randomness extractor over a large block instead, which is optimal up to negligible bias.

Trap: “Flip twice and XOR the results.” , which equals only when — exactly the case you don’t have. Another trap: “flip times and use the parity” — parity converges to fair as grows, but is never exactly fair for (bias decays as ), and von Neumann is exact in finite time.


D. Real-scenario reasoning

Q: A PM runs an A/B test, gets , and says “there’s a 97% chance the new feature works.” Historically only about 10% of the ideas we test actually have an effect, and our tests are powered at 80% with . What’s the actual probability the feature works?

Set up the notation.

  • = the feature genuinely has an effect. Base rate (the “prior odds that an idea in our pipeline works”).
  • = the test comes out statistically significant.
  • = power (this is the sensitivity).
  • = (this is the false positive rate).
  • Asked for: . The -value is — the opposite conditional.

Solution.

True positives: .

False positives: .

64%, not 97%. About one in three “wins” shipped on a significant result is nothing. The -value never was ; it’s , and converting between them requires the base rate of good ideas — which the -value has no access to.

Sanity check. Imagine 1,000 experiments from this pipeline. 100 features really work; 80 of them reach significance. 900 don’t work; 45 reach significance anyway. Of the 125 declared winners, 80 are real: . ✓ This table is the single most useful object to draw in an experimentation review.

Follow-up: “How do we make the winners trustworthy?” → Three levers, in order of effectiveness. (1) Raise the prior: test better ideas. Going from a 10% to a 30% hit rate moves precision to . (2) Tighten : at with the same power, . (3) Raise power: at 95% power with , — barely moves, because power only scales the (small) true-positive term. Note the asymmetry: at a low base rate, matters far more than power for the trustworthiness of a positive result — the same lesson as the fraud and screening problems. And (4): require replication, which multiplies the likelihood ratio.

Trap: means 3% chance it’s a fluke, 97% chance it’s real.” This is the single most common statistical error in industry. Related trap: reporting or as if either were a posterior.


Q: We’re trying to catch bot accounts. About 5% of signups are bots. Two signals: the request comes from a datacenter IP (70% of bots, 2% of humans), and the session has no mouse movement (90% of bots, 5% of humans). An account trips both. How confident are we it’s a bot?

Set up the notation.

  • = account is a bot, .
  • = datacenter IP. , .
  • = no mouse movement. , .
  • Assume conditional independence of and given the class. Flag this explicitly — it’s the load-bearing assumption and the interviewer is listening for it.
  • Asked for: .

Solution. Odds form, because it makes multiple signals trivial.

Prior odds: .

. .

97.1%. Two individually-imperfect signals combine to near-certainty because their likelihood ratios multiply: , enough to overcome 19-to-1 prior odds against. This multiplicativity in odds space (additivity in log-odds) is exactly what a logistic regression learns, and why log-odds is the natural currency for evidence.

Sanity check. Per 100,000 signups: 5,000 bots, of which trip both. 95,000 humans, of which trip both. . ✓ Also check the single-signal posteriors as a bound: datacenter IP alone gives odds , ; no-mouse alone gives , . Neither alone is actionable; together they are.

Follow-up: “Our real datacenter-IP and no-mouse signals are correlated — headless browsers do both. What happens?” → Conditional independence overstates the evidence. Suppose among humans, datacenter IP and no-mouse co-occur at rather than (a 4× positive dependence, since scrapers and privacy tools cause both). Then instead of 630, posterior odds , and — a drop from 97.1% to 89.2%, i.e. the false-positive rate on humans roughly quadruples. Correlated features cause naive Bayes to be overconfident, which in an enforcement system means banning real users. The fixes: model the joint directly (logistic regression on both features learns the correct combined weight), or de-duplicate features that measure the same underlying cause.

Trap: Adding the probabilities, or averaging and to get ~0.57. Evidence combines multiplicatively in odds, not additively in probabilities. Also: assuming conditional independence silently.


Q: Buses are supposed to come every 10 minutes on average. You show up at a random time and it always feels like you wait longer than 5 minutes. Are you imagining it?

Set up the notation.

  • Let be the gap between consecutive buses. Suppose the schedule has slipped so that half the gaps are 5 minutes and half are 15 minutes: , so — the advertised average is honest.
  • You arrive at a uniformly random time, not at a uniformly random gap. Let = the length of the gap you land in, and = your wait.
  • Asked for: and .

Solution. The key move: a random instant is more likely to fall inside a long gap, in proportion to the gap’s length. This is length-biased sampling.

75% of the time you land in a 15-minute gap, even though only half the gaps are long. Given you’re in a gap of length , your wait is uniform on , so :

The general formula:

Check: , so ✓. You are not imagining it: 6.25 > 5. And the excess is driven entirely by the variance of the gaps — with perfectly regular 10-minute buses, and exactly.

Sanity check. Take an extreme: gaps of 0 and 20 minutes, half each ( still). Then you land in a 20-minute gap with probability 1 and — double the naive answer, and obviously right, since the 0-length gaps occupy no time at all. ✓ Monte Carlo (1M random arrival times over 2M gaps): , . ✓

Follow-up: “Where else does this bite in practice?” → Everywhere you sample by encounter rather than by unit. (a) Class sizes: average class size 30, but ask students and you get a higher number, since more students sit in big classes. (b) Server latency: a random request in flight is more likely to be a slow one, so sampling in-flight requests overstates typical latency — this is why you measure at request arrival, not by snapshotting. (c) Queue monitoring: E[queue length seen by an arriving job] time-average length unless arrivals are Poisson (PASTA). (d) Survival/duration data: interviewing people currently unemployed oversamples long unemployment spells, biasing mean-duration estimates upward. The general name is the inspection paradox, and the general fix is to be explicit about your sampling frame: are you sampling gaps, or sampling time?

Trap: Answering 5 minutes (“half the mean gap”). That’s correct only for deterministic gaps. For exponential (Poisson) buses, gives — you wait a full mean gap, the memorylessness result that surprises people even more.


Q: You arrive in a new city and see a taxi numbered 60. Assuming taxis are numbered 1 through , estimate . Then: you see five taxis, the largest numbered 60. Now estimate .

Set up the notation.

  • Taxis numbered ; you observe a sample of size drawn without replacement (uniformly among the fleet you happen to see).
  • = maximum observed serial number. Here .
  • Asked for: an estimate of . Say which criterion you’re using — MLE and minimum-variance-unbiased give different answers, and the interviewer wants to see you distinguish them.

Solution.

MLE. The likelihood is for , zero otherwise — decreasing in . So . This is clearly biased low: it asserts you’ve seen the very last taxi.

Unbiased (the “German tank” estimator). Compute . For a sample of from without replacement,

Solve for :

Interpretation: estimates the average gap between observed serials, so you add one expected gap beyond the maximum.

  • , : .
  • , : .

Seeing five taxis with max 60 is strong evidence the fleet is small — if were 119, five draws would usually produce a maximum well above 60. More data tightens the estimate dramatically: the single-taxi estimate 119 has enormous variance, while the estimate is much sharper.

Sanity check. Verify unbiasedness by simulation at a known truth. Set , : theory says and . Monte Carlo (200k samples): , . ✓ Also check the degenerate case : exactly, as it must be. ✓

Follow-up: “Give me a Bayesian answer with an interval.” → With an improper prior (scale-invariant, the natural choice for an unknown magnitude) and observations with max , the posterior is for . For the mass decays like , so the distribution is sharply peaked at with a long right tail. Summing the posterior numerically gives median 68, mean 74.0, and a 95% upper credible bound of 107. So the honest report is: point estimate ~70, and the data is comfortably consistent with a fleet as large as 107. Reporting the interval is the difference between a good and a great answer — the point estimate alone hides how skewed the posterior is, and the frequentist estimate 71 sits just above the posterior median, as you’d expect for a right-skewed distribution.

Trap: Answering 60 (the MLE) without noting the bias, or answering 120 by the reasoning “on average I saw the middle taxi, so double it” — that’s the right instinct but it’s the answer, and it must be adjusted to (a taxi numbered 60 in a fleet of 120 is not the median; the comes from the discreteness). Applying to is the real error.


Q: We source a component from two factories. Factory A supplies 60% of our volume with a 2% defect rate; Factory B supplies 40% with a 5% defect rate. A customer returns a defective unit. Which factory should we call?

Set up the notation.

  • = unit came from Factory A, ; = Factory B, .
  • = unit is defective. , .
  • Asked for: and .

Solution. Total defect rate first:

Call Factory B: 62.5% likely. Note the reversal — A supplies more units but B supplies more defects, because B’s 2.5× worse defect rate more than compensates for its 0.67× share. The prior favors A () and the likelihood ratio favors B (), and the likelihood wins: posterior odds . ✓

Sanity check. Per 10,000 units: 6,000 from A → 120 defective. 4,000 from B → 200 defective. Total 320 defective (matching ✓), of which 200 are B’s: . ✓

Follow-up: “What’s the biggest quality win available to us?” → Decompose the 3.2% defect rate: A contributes 1.2 percentage points, B contributes 2.0. Options: (a) shift volume — moving to 100% Factory A gives , a 37.5% reduction; (b) fix B — bringing B to A’s 2% gives , the same 37.5% reduction; (c) halve B’s rate to 2.5% gives , a 31% reduction. So volume-shifting and fixing B are equivalent in effect, and the decision is about cost and supply risk, not probability. The general principle: attack the term contributing the most mass to the total, which here is .

Trap: Answering A because it’s the bigger supplier — using the prior and ignoring the likelihood. The mirror trap: answering B “because 5% > 2%” without computing, which gets the right answer for the wrong reason and falls apart if the volumes were 95/5 (then and you should call A).


Q: An interviewer and a candidate each have three one-hour slots free tomorrow, chosen independently and uniformly at random from a 9-to-5 workday. Actually, simpler version: each independently picks a random one-hour block starting anywhere in a 4-hour window. What’s the probability their blocks overlap?

Set up the notation.

  • The window is hours. Each person’s block is and respectively, where the block must fit inside the window, so the start times satisfy , independent.
  • = the blocks overlap. Two intervals of length 1 overlap iff their starts are within 1 hour: .
  • Asked for: .

Solution. This is a geometric probability on the square , total area 9.

The complement is two corner triangles, each with legs of length :

5/9, about 55.6%. General form: for blocks of length in a window of length (so starts are uniform on ), when . Here ✓. The intuition worth stating: overlap is likely — better than a coin flip — because two 1-hour blocks in a 4-hour window are crowded, and coordination failures are the exception rather than the rule.

Sanity check. Extremes. If (each block fills the window), starts are both 0 and overlap is certain: formula gives — degenerate, so check : starts uniform on , , and indeed two 2-hour blocks in a 4-hour window must touch. ✓ If , , as two instants never coincide. ✓ Monte Carlo (4M): 0.5558. ✓

Follow-up: “Now three people. What’s the probability all three pairwise overlap — i.e. there’s a time all three are free?” → All three intervals of length 1 share a common point iff , i.e. the range of three variables is under 1. For uniforms on , for . With : . Overlap probability collapses fast with more participants — from 5/9 for two to 7/27 for three — which is the arithmetic behind why scheduling a 5-person meeting requires a tool.

Trap: Treating the start times as uniform on instead of , which allows blocks to run past the end of the window and gives the wrong denominator. Also: computing as by treating the difference as uniform — the difference of two uniforms is triangular, not uniform.


Q: We run two independent filters in sequence on incoming content — anything flagged by both goes to human review. Filter 1 has 90% recall and a 5% false-positive rate; Filter 2 has 85% recall and a 10% false-positive rate. Violating content is 2% of the stream. What does the review queue look like?

Set up the notation.

  • = content violates policy, .
  • = flagged by filter 1, filter 2.
  • , ; , .
  • Conditional independence given the class — stated, and revisited in the follow-up.
  • Asked for: , plus the volume.

Solution. Combined recall and combined FPR:

True positives: . False positives: .

75.7% precision at 76.5% recall, with a queue volume of of the stream. Compare Filter 1 alone: precision (26.9%) at 90% recall, with a queue of 6.7% of the stream. Cascading multiplies the FPRs (0.05 × 0.10 = 0.005, a 20× reduction) while only mildly degrading recall (0.90 → 0.765), which is why AND-ing weak independent filters is such an effective pattern: precision 2.8×, queue volume down 3.3×, recall down only 15%.

Sanity check. Per 1,000,000 items: 20,000 violating → double-flagged. 980,000 clean → double-flagged. Queue ; precision ✓. And the missed violations: get through — the cost of the cascade.

Follow-up: “The filters share a training set and both key off profanity. What breaks?” → Correlated errors destroy the multiplication. If rather than (a 4× dependence, because the same benign-but-profane content trips both), false positives become and precision falls to — from 76% to 44%. The entire benefit of a cascade comes from error independence, so you should measure the joint FPR empirically rather than multiplying, and deliberately build the filters on different features, different data, and different model families. A cascade of two copies of the same model gains you nothing.

Trap: Multiplying recalls but forgetting to multiply the FPRs too (or vice versa), and — the big one — assuming independence without checking. A secondary trap: reporting the cascade as strictly better. It isn’t: recall dropped from 90% to 76.5%, so 4,700 violations per million now go undetected instead of 2,000.


Q: Here’s data from a treatment for kidney stones. Treatment A succeeded in 273 of 350 cases; Treatment B in 289 of 350. B looks better. But when I split by stone size, A wins for small stones and for large stones. How is that possible, and which treatment should I recommend?

Set up the notation.

  • = treatment. = success. = stone size, a confounder.
  • The paradox is a statement about versus .

Solution. The table:

Small stonesLarge stonesOverall
Treatment A81/87 = 93.1%192/263 = 73.0%273/350 = 78.0%
Treatment B234/270 = 86.7%55/80 = 68.8%289/350 = 82.6%

So and , yet .

How. Look at the confounder’s distribution across treatments:

Small stones are easier (success ~90% vs ~70%), and Treatment B was given overwhelmingly to easy cases while A took the hard ones. B’s high aggregate rate is inherited from its patient mix, not its efficacy. Algebraically, the aggregate is a weighted average,

and B’s weights sit on the high-success stratum. There is no arithmetic contradiction — a weighted average with different weights can reverse a uniform pointwise ordering.

Which to recommend: A. The stratified comparison is the causal one here, because stone size is a pre-treatment variable that influenced treatment assignment (surgeons chose open surgery for the hard cases). Standardize to a common population — say 50/50 small/large:

A wins by 5.4 points once the mix is equalized.

Sanity check. Verify the aggregates add up: A is of ✓; B is of ✓. Then check the direction of the confounding qualitatively before trusting the reversal: B’s advantage should vanish if you give both treatments the same case mix — and it does. A quick bound: A’s worst stratum rate (73.0%) is below B’s overall rate (82.6%), which is exactly the room the paradox needs.

Follow-up: “When should I not stratify?” → When the stratifying variable is a collider or a mediator, not a confounder. If is affected by the treatment (e.g. you stratify a drug trial by post-treatment blood pressure, which the drug changes), conditioning on it blocks part of the causal effect and can manufacture spurious reversals — this is Berkson’s paradox territory and “adjusting for post-treatment variables” is a classic way to ruin a good experiment. The decision rule is causal, not statistical: draw the DAG. Adjust for common causes of treatment and outcome; do not adjust for descendants of the treatment. No amount of looking at the numbers tells you which analysis is right — the two tables are equally valid descriptions, and only the causal structure picks one.

Trap: Recommending B from the aggregate. Almost as bad: declaring the data “contradictory” or a computational error. It’s neither — both views are arithmetically correct, and the resolution requires knowledge outside the table.


E. Counting and combinatorics that show up

Q: You’re dealt five cards from a standard deck. What’s the probability of a full house?

Set up the notation.

  • Deck of 52, hands are unordered 5-subsets, all equally likely.
  • .
  • Full house = exactly three cards of one rank and exactly two of another.

Solution. Count the hands.

  • Choose the rank for the triple: ways.
  • Choose 3 of its 4 suits: .
  • Choose a different rank for the pair: ways.
  • Choose 2 of its 4 suits: .

About 0.144%, or 1 in 694 hands. The count is small mainly because you’re forcing 3 of 4 suits in one rank and 2 of 4 in another — most rank-pairs of hands leak a fifth card that breaks the pattern.

Sanity check. Two checks. (1) Exhaustive enumeration: iterating all 2,598,960 five-card subsets and classifying them gives exactly 3,744 full houses ✓ (and 4 of a kind: 624, flush excluding straight flush: 5,108, straight: 10,200, three of a kind: 54,912, two pair: 123,552, one pair: 1,098,240, high card: 1,302,540, straight flush: 40 — summing to 2,598,960 ✓, which validates the whole classification). (2) Ordering check: the ranks are ordered — the triple rank and pair rank play different roles — so use , not . If you’d used you’d get 1,872, exactly half, which is the classic error and the reason to sanity-check by asking “is my selection ordered or unordered?”

Follow-up: “And four of a kind? Which is rarer, and by how much?” → Four of a kind: choose the rank (13), take all four suits (), choose any 1 of the remaining 48 cards (48). Count , so . Four of a kind is exactly 6× rarer than a full house, which is why it outranks it. The factor is transparent from the two counts: both start with 13 choices of primary rank, then full house contributes while four of a kind contributes , and .

Trap: Using for the two ranks (halves the answer), or forgetting to exclude the case where the pair’s rank equals the triple’s rank (impossible anyway, but people write ).


Q: Same deal, five cards. Probability of a flush? And then: you’re playing draw poker, you have four hearts and one off-suit card, and you discard the off-suit card for one new card. What’s the probability you complete the flush?

Set up the notation.

  • Flush = all five cards the same suit. Poker convention excludes straight flushes (they’re a higher hand), so count “flush but not straight flush.” State which convention you’re using.
  • For the draw: you hold 4 hearts. Your 5 seen cards are gone from the deck; cards remain unseen, of which are hearts.

Solution — flush probability.

All five same suit: .

Subtract straight flushes: each suit has 10 straights (A-5 through 10-A), so .

About 0.197%, or 1 in 509 hands — so a flush is about 1.36× more common than a full house, which is why it ranks below it.

Solution — the draw. Now the conditional. 47 unseen cards, 9 of them hearts:

(If instead you frame it as “given the first four dealt cards were hearts, is the fifth a heart,” the deck has 48 unseen cards with 9 hearts: . The two differ only in whether the discarded card is counted as known — a good illustration that what you condition on changes the denominator, and you must say which.)

Sanity check. Exhaustive enumeration of all hands: 5,108 flushes and 40 straight flushes ✓. For the draw, sanity-check the fraction: you need 9 specific cards out of 47, and is close to the poker player’s rule of thumb “4 outs ≈ 8%, 9 outs ≈ 19% on one card” (the “rule of 2”: outs × 2 ≈ percent per card). ✓ Monte Carlo (1.5M hands): flush frequency 0.00192 (within 1.5 SE of 0.001965), and vs 0.1875 (1.5 SE). ✓

Follow-up: “Two chances at it — flop and turn in hold’em, 9 outs. Probability of hitting?” → With 47 unseen after the flop and 9 outs, , so , about 35%. Note this is less than : the two events aren’t disjoint, and with , giving — close (the small residual is because must be computed unconditionally). The player’s “rule of 4” (outs × 4 = 36%) is a decent approximation.

Trap: Reporting without excluding straight flushes — a small error numerically but the interviewer is checking whether you know the convention. Bigger trap on the draw: using or instead of conditioning on the cards you’ve seen.


Q: Eight people — five men and three women — line up at random for a photo. What’s the probability no two women end up standing next to each other?

Set up the notation.

  • All orderings of the eight distinct people are equally likely.
  • = no two women are adjacent.
  • Asked for: .

Solution. Use the gap method: place the unrestricted group first, then slot the restricted group into the gaps.

  • Arrange the 5 men: ways. This creates gaps (including the two ends):
  • Choose 3 of these 6 gaps for the women: . Putting at most one woman per gap guarantees no two are adjacent.
  • Arrange the 3 women in the chosen gaps: .

5/14, about 35.7%. Note the clean alternative form: — since only the set of positions occupied by women matters, you can ignore identities entirely and ask “what fraction of 3-subsets of 8 positions contain no two consecutive integers?”

Sanity check. Exhaustive enumeration of all 40,320 permutations: exactly 14,400 satisfy the condition ✓. Second check via the position-subset form: the number of 3-subsets of with no two consecutive is out of ✓ — the general identity for no-two-adjacent -subsets of , worth knowing. Monte Carlo (1M): 0.3574. ✓

Follow-up: “What if they line up in a circle instead?” → Circular arrangements kill the two “end” gaps, since position 1 and position 8 are now adjacent. Fix one man’s seat to break rotational symmetry: arrange the remaining 4 men in ways, creating exactly 5 gaps between the 5 men (no ends), and choose 3: , times for the women. So out of circular arrangements, giving . Lower than 5/14 = 0.357, as it must be — the circle removes the two safe end slots.

Trap: Computing the complement by inclusion-exclusion and botching it: “P(some two adjacent) = 3 pairs × P(a given pair adjacent)” double-counts the all-three-adjacent cases. The gap method sidesteps inclusion-exclusion entirely and is the technique to reach for whenever the constraint is “no two of these are adjacent.”


Q: Six people are in a meeting. What’s the probability at least two share a zodiac sign?

Set up the notation.

  • 12 signs, assumed equally likely and independent across people (both are approximations — birth rates aren’t uniform across months, which we’ll revisit).
  • , . = at least one shared sign. Compute via the complement.

Solution.

Reduce: .

About 77.7% — far higher than most people guess for only 6 people and 12 categories. The reason is the same as the birthday problem: there are pairs, and 15 pairs each with a chance of matching gives an expected 1.25 matches. Once expected matches exceed 1, sharing is the norm.

Sanity check. Poisson approximation: , so . Same ballpark, and low by about 6 points — the Poisson approximation treats the 15 pairwise matches as independent, which is only accurate when , and here . It reliably errs in this direction, so use it as a lower bound. The rule says the 50% point is at people, and 6 > 4.08, so we should indeed be well above 50%. ✓ Monte Carlo (1.5M): 0.77717. ✓

Follow-up: “Birth months aren’t actually uniform. Does that push the probability up or down?”Up, always. Non-uniformity increases collision probability. Formally, — simpler argument: for two people, by Cauchy–Schwarz (or Jensen), with equality only for the uniform distribution. So any deviation from uniformity raises the per-pair match probability, and hence raises . The uniform assumption gives a lower bound — a useful thing to say, because it means 77.7% is conservative. This is also why hash functions are designed to be near-uniform: any clumping strictly increases collisions.

Trap: , or “” — the latter answers “does anyone share my sign,” which involves 5 comparisons, not 15 pairs.


Q: In our product, 50% of users use feature A, 40% use B, 30% use C. 20% use both A and B, 15% use A and C, 10% use B and C, and 5% use all three. What fraction of users use at least one feature? And of the users who use at least one, what fraction use exactly one?

Set up the notation.

  • = uses that feature. Given: , , , , , , .
  • Note the pairwise figures are not “exactly two” — they include the triple. Establishing that is the single most important step; if the interviewer means “exactly,” every number changes.
  • Asked for: , then .

Solution. Inclusion-exclusion:

80% use at least one feature (so 20% use none).

Now peel the Venn diagram into its seven regions:

  • Only :
  • Only :
  • Only :
  • Exactly : ; exactly : ; exactly :
  • All three:

56.25% of engaged users touch only a single feature — the shape of nearly every real product, where a majority of active users are single-feature users and cross-feature adoption is the minority.

Sanity check. The seven regions plus “none” must sum to 1: , plus none ✓. Every region is non-negative, which confirms the given numbers describe a consistent joint distribution (a good thing to verify — interviewers sometimes hand you impossible numbers to see if you notice; e.g. if had been with it would be contradictory since ). Monte Carlo sampling from the reconstructed 8-atom distribution (8M draws): union 0.79968, conditional 0.5626 ✓.

Follow-up: “What fraction of users use at least two features?” → Two routes. Direct: . Or by the identity ✓, and . The general “at least ” identity from inclusion-exclusion, where is the sum of -wise intersections, is worth carrying. As a share of engaged users: , the complement of 56.25% ✓.

Trap: Adding and either reporting it or clamping to 1.0. Second trap: reading “20% use both A and B” as “exactly A and B,” which would make the union -style corrections necessary and yield a different answer — always ask.


Q: Five people check their hats at a restaurant. The attendant loses the tickets and hands the hats back at random. What’s the probability nobody gets their own hat?

Set up the notation.

  • A hat assignment is a permutation of ; all are equally likely.
  • Person gets their own hat iff , a fixed point.
  • = no fixed points, i.e. is a derangement.
  • Asked for: where counts derangements.

Solution. Inclusion-exclusion over the events . There are ways to fix a specific set of people, and permutations of the rest:

For :

11/30, about 36.7%. And the striking part: as ,

The answer is essentially regardless of how many people there are — 5 hats or 5,000, it’s about 36.8%. Convergence is ferociously fast (the error is under , so at we’re already within ).

Sanity check. Exhaustive enumeration of all 120 permutations of 5 elements gives the fixed-point distribution: 0 fixed points 44 times, 1 fixed point 45, 2 fixed points 20, 3 fixed points 10, 4 fixed points 0, 5 fixed points 1 — summing to 120 ✓. (Note there is no permutation with exactly 4 fixed points: if four people get their own hat, the fifth must too.) Also exactly, for every — and the enumeration confirms ✓. Since the count is approximately Poisson(1), , which is a second derivation of the limit. Monte Carlo (1M): , , mean 1.0017. ✓

Follow-up: “What’s the probability exactly one person gets their own hat?” → Choose which person (), then derange the other four ():

Slightly more likely than nobody getting theirs (0.3667), which surprises people. Both converge to from opposite sides, consistent with Poisson(1) having .

Trap: Computing by treating the five events as independent. They aren’t — permutations impose a global constraint (this is sampling without replacement), and the independence approximation is off by 4 percentage points here. Second trap: from naive inclusion-exclusion truncated at the first term.


Q: Ten identical background jobs are dispatched to four servers, each job going to a uniformly random server independently. What’s the probability every server gets at least one job? And I’m going to push back on your counting.

Set up the notation. The pushback is the point, so get the model right first.

  • Jobs are independently and uniformly assigned, so the natural sample space is functions from 10 jobs to 4 servers: equally likely outcomes. The jobs are physically identical but distinguishable for probability purposes, because each one independently makes its own choice.
  • = every server receives job. Asked for: .

Solution. Inclusion-exclusion on the events = “server gets nothing.” .

About 78.1% — so roughly a 22% chance at least one server idles, which is high enough to matter for capacity planning and is the reason random load balancing under-utilizes at low job counts.

Now the pushback: the stars-and-bars answer. A tempting route: the number of ways to distribute 10 identical items into 4 bins is , and the number with every bin non-empty is , giving . This is wrong — off by a factor of 2.7 — because stars and bars counts multisets (occupancy vectors like ), and those are not equally likely under independent uniform assignment. The vector has multinomial weight , while has weight 1. Stars and bars is the right count for the wrong measure. Use it for counting configurations; never use its ratio as a probability unless the problem explicitly says all occupancy vectors are equally likely (Bose–Einstein statistics, which describes bosons, not job schedulers).

Sanity check. Bound it with the union bound: , so — consistent with 0.7806, and tight because the higher-order terms are tiny. ✓ Complement check: exact , versus the union bound 0.2253; the gap is essentially the double-counting correction ✓. Monte Carlo (1.5M): 0.78051. ✓

Follow-up: “How many jobs before we’re 99% sure no server idles?” (union bound, tight here). Set : , , so jobs. Exact check at : via inclusion-exclusion gives ✓. This is the coupon-collector regime — you need jobs to cover servers, here for the expected cover time but ~21 for 99% confidence.

Trap: The stars-and-bars ratio . It’s the most common wrong answer to this problem and the reason interviewers ask it — they want to see whether you distinguish “counting configurations” from “assigning probabilities.”


Q: You sample 100 user IDs uniformly at random with replacement from a pool of 100 users. How many distinct users do you expect to see?

Set up the notation.

  • users, draws, i.i.d. uniform.
  • = number of distinct users appearing. Define indicators if user appears at least once, . Then .
  • Asked for: . Use linearity of expectation — do not try to find the distribution of , which is messy.

Solution.

About 63.4 distinct users, so about 36.6 users are never sampled. The clean asymptotic: when and is large, , so

Sampling items with replacement from only reaches about 63.2% of them — the fact behind bootstrap resampling (each bootstrap sample omits ~36.8% of the data, which is exactly the out-of-bag set used to validate random forests).

Sanity check. Bound it: ✓, and the number you’d get if every draw collided maximally, ✓. Better check via expected collisions: expected number of duplicate draws is ; independently, the expected number of ordered colliding pairs is , which overcounts multi-way collisions but is the right order of magnitude ✓. Monte Carlo (1M): 63.3971 vs 63.3968 — agreement to 4 decimal places. ✓

Follow-up: “How many draws to see every user at least once?” → That’s the coupon collector problem, and the answer is a different object: where is the harmonic number. For : , so draws — five times the pool size. The derivation is again linearity: after collecting distinct users, the wait for a new one is geometric with , so . Note the asymmetry worth pointing out: 100 draws gets you 63% of the way, but the last 37% costs another 419 draws — the tail of the coupon-collector problem is brutally slow, with total and the final coupon alone taking .

Trap: Answering 100 (“I drew 100 IDs”), which confuses draws with distinct values. Or attempting the exact distribution of via Stirling numbers of the second kind () — correct but wildly unnecessary when linearity of expectation gives the answer in one line. Interviewers use this to check whether you reach for indicators.


Q: A committee of 4 is chosen at random from 6 men and 4 women. What’s the probability of at least 2 women? And given that there are at least 2 women, what’s the probability there are exactly 2?

Set up the notation.

  • Choose 4 from 10 people; all committees equally likely.
  • = number of women on the committee. .
  • Asked for: , then .

Solution. Count each case as :

countprobability
0
1
2
3
4

Total: ✓.

About 54.8% chance of at least 2 women; and given at least 2, a 78.3% chance it’s exactly 2. The conditional is high because is the modal outcome and the conditioning event’s other cases () are comparatively rare — conditioning on “at least ” concentrates almost all the mass on exactly whenever the distribution is decreasing past its mode.

Sanity check. The counts summing to is the check (it’s Vandermonde’s identity, ). Second check: ; from the table, ✓. Since the mean is 1.6, near one-half is exactly what you’d expect. Monte Carlo (1M): 0.54688 and 0.78285. ✓

Follow-up: “Given the committee has at least one woman, what’s the probability it has at least one man?”. The committees with at least one woman and at least one man exclude both all-male (15) and all-female (1): . So

Almost certain, because the only excluded case is the single all-women committee. Worth noting how conditioning reshapes things: unconditionally , and conditioning on a woman being present barely moves it — but it does move it, downward, since women and men compete for the same 4 seats (negative dependence, the hypergeometric signature).

Trap: Treating the four selections as independent binomials with : , versus the true 0.5476. Close, but wrong — selection is without replacement from a small pool, so you need the hypergeometric. The other trap is answering the marginal when asked for the conditional .


Appendix: Verification code

This is verification code, not interview code. In an interview you write the analytic solution; these scripts exist only to confirm the numbers above. Every problem in this document was checked either by Monte Carlo (typically trials, enough for three stable significant figures) or by exhaustive enumeration where the state space is small enough. Run these to reproduce the checks on the eight trickiest problems.

import numpy as np, math
from itertools import permutations, combinations
from collections import Counter
rng = np.random.default_rng(0)

# ---- B1: Monty Hall, both host protocols -------------------------------
n = 2_000_000
car, pick = rng.integers(0, 3, n), rng.integers(0, 3, n)
host = np.empty(n, dtype=int)
for i in range(3):                      # knowledgeable host
    for j in range(3):
        m = (car == i) & (pick == j)
        opts = [k for k in range(3) if k != i and k != j]
        host[m] = opts[0] if len(opts) == 1 else np.where(
            rng.random(m.sum()) < .5, opts[0], opts[1])
print("MH switch:", ((3 - pick - host) == car).mean())        # 0.6667 = 2/3
hostr = np.empty(n, dtype=int)          # random host
for j in range(3):
    m = pick == j
    o = [k for k in range(3) if k != j]
    hostr[m] = np.where(rng.random(m.sum()) < .5, o[0], o[1])
ok = hostr != car                       # condition on a goat being revealed
print("MH random-host switch:", ((3 - pick - hostr) == car)[ok].mean())  # 0.5

# ---- B3: two children, "at least one boy born Tuesday" -----------------
n = 8_000_000
sex, day = rng.integers(0, 2, (n, 2)), rng.integers(0, 7, (n, 2))
cond = ((sex == 1) & (day == 0)).any(1)
print("Tuesday boy:", (sex.sum(1) == 2)[cond].mean(), "vs", 13/27)  # 0.4815

# ---- B6: two envelopes, conditional vs unconditional -------------------
n = 4_000_000
pair = rng.integers(0, 2, n)
small = np.where(pair == 0, 10, 20); big = 2 * small
hold_small = rng.random(n) < .5
mine  = np.where(hold_small, small, big)
other = np.where(hold_small, big, small)
s20 = mine == 20
print("E[other | see 20]:", other[s20].mean())        # 25.0  -> swap looks good
print("E[gain from always swapping]:", (other - mine).mean())   # 0.0

# ---- B7: Sleeping Beauty, both reference classes ------------------------
n = 2_000_000
h = rng.random(n) < .5
print("frac of AWAKENINGS that are heads:", h.sum() / (h.sum() + 2*(~h).sum()))  # 1/3
print("frac of RUNS that are heads:      ", h.mean())                            # 1/2

# ---- C7: waiting times for HH vs HT ------------------------------------
def wait(pattern, n=400_000):
    L = len(pattern); cnt = np.zeros(n); done = np.zeros(n, bool)
    buf = np.full((n, L), 'X', dtype='<U1'); t = 0
    tgt = np.array(list(pattern))
    while not done.all() and t < 10_000:
        t += 1
        buf[:, :-1] = buf[:, 1:]
        buf[:, -1] = np.where(rng.random(n) < .5, 'H', 'T')
        new = (~done) & (buf == tgt).all(1)
        cnt[new] = t; done |= new
    return cnt.mean()
print("E[T_HH]:", wait("HH"), " E[T_HT]:", wait("HT"))   # 6.0 and 4.0

# ---- C8: von Neumann fair bit from a p=0.3 coin -------------------------
n = 2_000_000
a, b = rng.random(n) < .3, rng.random(n) < .3
use = a != b
print("output bias:", a[use].mean(), " flips/bit:", 2/use.mean(), "vs", 1/(.3*.7))

# ---- D3: inspection paradox (gaps of 5 and 15 min) ---------------------
gaps = np.where(rng.random(2_000_000) < .5, 5.0, 15.0)
cum = np.cumsum(gaps)
t = rng.random(1_000_000) * cum[-1]      # arrive at a uniformly random INSTANT
i = np.searchsorted(cum, t)
print("E[wait]:", (cum[i] - t).mean(), " P(landed in 15-gap):", (gaps[i] == 15).mean())
# 6.25 and 0.75 -- not 5.0 and 0.5

# ---- E7: bins, and why stars-and-bars is the wrong measure -------------
n = 1_500_000
b = rng.integers(0, 4, (n, 10))
print("P(all 4 servers busy):",
      np.stack([(b == j).any(1) for j in range(4)], 1).all(1).mean())   # 0.7806
print("  exact:", sum((-1)**k * math.comb(4,k) * (4-k)**10 for k in range(5)) / 4**10)
print("  stars-and-bars ratio (WRONG):", math.comb(9,3) / math.comb(13,3))  # 0.2937

# ---- E1/E2: exhaustive 5-card enumeration ------------------------------
deck = [(r, s) for r in range(13) for s in range(4)]
cnt = Counter()
for hand in combinations(deck, 5):
    shape = sorted(Counter(r for r, _ in hand).values(), reverse=True)
    flush = len({s for _, s in hand}) == 1
    rk = sorted({r for r, _ in hand})
    straight = len(rk) == 5 and (rk[4]-rk[0] == 4 or rk == [0,1,2,3,12])
    if flush and straight: cnt['straight flush'] += 1
    elif shape == [4,1]:   cnt['four of a kind'] += 1
    elif shape == [3,2]:   cnt['full house'] += 1
    elif flush:            cnt['flush'] += 1
    elif straight:         cnt['straight'] += 1
print(dict(cnt), "of", math.comb(52,5))
# full house 3744, flush 5108, four of a kind 624, straight 10200, straight flush 40

# ---- E6: derangements by exhaustive enumeration -------------------------
fp = Counter(sum(1 for i in range(5) if p[i] == i) for p in permutations(range(5)))
print("fixed-point counts:", dict(fp), " P(0)=", fp[0]/120, "=11/30, 1/e =", 1/math.e)

Verification summary. All 41 problems were checked. Numeric answers were confirmed by Monte Carlo at trials; every agreement is within 1.7 standard errors of the analytic value, and pure-counting problems (Section E) were additionally confirmed by exhaustive enumeration — all five-card hands, all orderings of eight people, all permutations of five hats. The two places where simulation matters most conceptually are B6 (the conditional expectation genuinely favors swapping while the unconditional gain is exactly zero — both reproduced) and E7 (the simulation decisively rejects the stars-and-bars ratio of 0.294 in favor of 0.781).