skip to content

questions

5

A nightly job must count records matching none of k taint filters - why must the correction terms alternate in sign?

level: middleimportance: must knowfreq 66%

answer

  1. over-correct, then correct the correction
  2. start from the total, remove each filter
  3. pairs come back, triples go out again
  4. a j-filter term carries sign (-1)^j
  5. (1-1)^m = 0 for every tainted record

basics

~20 s

Subtracting each filter's matches over-corrects records caught by several filters, so pairwise overlaps are added back, triples removed again, and so on. The alternating signs make every record matching at least one filter cancel to exactly zero.

solid answer

~50 s

Start from the total `N` and subtract each filter's match count. A record caught by two filters has now been removed twice, so you add every pairwise intersection back; a record caught by three has been removed three times and restored three times, so it is still counted and the triples must come out again. The general shape is `N - sum|Ai| + sum|Ai and Aj| - sum|Ai and Aj and Ak| ...`, where a term built from `j` filters carries the sign `(-1)^j`. The alternation is not a convention: a record caught by exactly `m >= 1` filters contributes `sum_j (-1)^j C(m,j)`, which is the binomial expansion of `(1-1)^m` and therefore zero, while a clean record is counted once by the leading `N`. Every term is needed - stopping early leaves a bound rather than the count.

go deeper

for a junior

Recall the shape: add the parts, subtract the shared pieces, add the shared-by-three pieces back. Knowing that plain addition double counts anything caught twice is already the main idea.

for a middle

Explain the mechanics: what the sign of a j-filter term is, why the correction has to keep alternating, and that a record caught by m filters contributes a signed binomial row summing to zero.

for a senior

Show the operational judgment: where the intersection counts actually come from, what a truncated sum buys when the deep terms are unmeasurable, and which direction the resulting bound points.

for a principal

Frame the trade-off: whether the reporting layer should expose arbitrary intersection counts at all, or whether the conditions should be restructured into disjoint segments so no signed sum is needed.

## The counting problem A nightly deduplication job ingests several overlapping feeds and runs `k` **taint filters** over the merged stream - a filter marks a record as suspect for some reason (a blocked source, a malformed key, a stale timestamp). What the pipeline must report is the number of **clean** records: those that trip *none* of the filters. The only figures available from the reporting layer are match counts - how many records each filter caught, and how many were caught by a given combination of filters. The naive move is to add up the per-filter counts, subtract that from the total, and ship it. That is wrong whenever two filters can catch the same record, which is exactly the situation the job exists for. ## Why one subtraction over-corrects Write `N` for the total number of records and `A1 ... Ak` for the sets of records each filter catches. Follow a single record through the arithmetic: - a record caught by **no** filter is counted once in `N` and never touched again - correct; - a record caught by **one** filter is counted once, subtracted once - correct, it reaches zero; - a record caught by **two** filters is counted once and subtracted **twice** - it now contributes `-1`, so the count of clean records comes out too low; - a record caught by **three** filters is subtracted three times, contributing `-2`. So the first correction does not merely fail to be exact; it drives the answer in a direction that grows with how much the filters overlap. Adding every pairwise intersection back fixes the two-filter records, but a three-filter record sits in three different pairwise intersections and is now restored three times, landing back at `+1`. That is what forces the next subtraction, and the pattern does not stop until the intersections run out. ## The general statement The **inclusion-exclusion principle** states the clean count directly: `clean = N - sum |Ai| + sum |Ai and Aj| - sum |Ai and Aj and Ak| + ... + (-1)^k |A1 and ... and Ak|` A term built from an intersection of `j` filters carries the sign `(-1)^j`. There is one term for every subset of the `k` filters, including the empty subset whose intersection is the whole population and which supplies the leading `N`. That is `2^k` terms in total. The union form - the count of records caught by **at least one** filter - is the same identity rearranged, with `2^k - 1` non-empty terms and the signs starting negative. ## Why the alternation cancels exactly Take a record caught by exactly `m` filters and ask how many terms it appears in. It appears in every term built from a subset of *those* `m` filters, and there are `C(m,j)` such subsets of size `j`. Its net contribution is therefore the signed binomial row for `m`: | filters matched (m) | contributions by term size | net | |---|---|---| | 0 | +1 | 1 | | 1 | +1, -1 | 0 | | 2 | +1, -2, +1 | 0 | | 3 | +1, -3, +3, -1 | 0 | | m | sum of (-1)^j C(m,j) | (1-1)^m = 0 | The last row is the whole argument: the signed row sum is the binomial expansion of `(1 - 1)^m`, which is `0` for every `m >= 1` and `1` for `m = 0`. Every tainted record cancels itself out no matter how many filters caught it, and every clean record survives with weight one. Nothing about the filters is assumed - not independence, not disjointness, not similar sizes. It is an identity over finite sets, so it holds for whatever the data happens to look like. ## Stopping early on purpose Because the terms alternate, a **truncated** sum is not noise - it brackets the answer, and the direction depends on where you stopped. Summing the per-filter counts alone over-states the union (every multiply-caught record is counted more than once), so it gives an upper bound on the union and hence a lower bound on the clean count. Subtract the pairwise overlaps and you undershoot the union, which flips both bounds. Truncation is a legitimate engineering move when the deep intersections are expensive to measure, but it must be reported as a bound, never as the count. ## Where engineers get this wrong 1. **Stopping after the single subtraction**, which is only correct when no record can be caught twice - the case where the formula was not needed. 2. **Adding pairs back and stopping there**, which leaves triple-caught records mis-weighted and is the most common half-remembered version. 3. **Reaching for independence**, multiplying rates as if the filters were unrelated. Overlapping feeds correlate heavily, and the identity never needs that assumption anyway. 4. **Forgetting the empty term.** The leading `N` is a term of the sum, and dropping it turns the clean count into the negated union.

  • If the deepest intersections are too expensive to measure, what does a truncated sum still give you?
    A bound with a known direction. Summing the per-filter counts alone over-states the union, so it is an upper bound on the union and therefore a lower bound on the clean count. Subtracting the pairwise overlaps under-states the union and flips both bounds. Each extra group of terms tightens the bracket, so you can report an interval and say where you stopped.
  • Does the identity require the filters to be independent, or the sets to be similar in size?
    Neither. It is a counting identity over finite sets, proved by showing each element's signed contributions cancel, so it holds for arbitrarily correlated filters and wildly uneven sizes. Independence is a probabilistic assumption that would let you multiply rates instead - a different and usually false claim about overlapping feeds.
  • How many terms does the exact clean count need for k filters?
    `2^k`, one for every subset of the filters, including the empty subset that contributes the total population size. The union form has `2^k - 1`. Each term is a real measurement - the size of one intersection - so the cost is in the measurements, not the arithmetic.

saying these in an interview costs you the question

  • Subtracting every filter's count once and stopping there
  • Adding the pairs back but never removing the triples
  • Calling the alternating signs an arbitrary convention
  • Assuming the filters must be independent to combine
  • Treating a truncated sum as the exact count rather than a bound
  • Dropping the leading total and returning the union instead
open as a page

Using inclusion-exclusion, how do you count the IDs from 1 to 1000 divisible by none of 2, 3 and 5?

level: middleimportance: must knowfreq 50%

basics

~10 s

Subtract from 1000 the multiples of 2, 3 and 5, add back the multiples of 6, 10 and 15, then subtract the multiples of 30. That is 1000 - 734 = 266 surviving IDs.

open as a page

In a rebalance where no shard may stay on its former host, what fraction of all n! reassignments qualify?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Roughly 37 percent - about 1/e - and from n = 5 onward the fraction barely moves as n grows. These no-fixed-point arrangements are derangements, counted by an alternating sum over the shards that could have stayed put.

open as a page

With 20 overlapping taint filters the avoid-all sum needs 2^20 terms - how do you decide what to compute instead?

level: principalimportance: should knowfreq 30%

basics

~20 s

Decide by what you can touch. With the raw records in reach, one pass evaluating a compound predicate costs about n times k and is exact; the signed sum is for when only aggregate set sizes are available, and at twenty filters its million terms mean a million measurements.

open as a page

How do you count the ways to place n distinct records into k named buckets with no bucket left empty?

level: seniorimportance: nice to knowfreq 24%

basics

~20 s

Take all k^n placements and remove those that miss at least one bucket by an alternating sum: sum over j of (-1)^j C(k,j) (k-j)^n. For 5 records into 3 buckets that is 243 - 96 + 3 = 150.

open as a page