skip to content

For a lossless scheme, what fraction of fixed-length inputs can shrink by at least 10 bits?

level: middleimportance: nice to knowfreq 21%

answer

  1. count the short-enough outputs
  2. lengths sum to a power of two
  3. one more bit saved halves the winners
  4. under one in 2^(k-1)
  5. fraction does not depend on n

basics

~20 s

Fewer than one input in 512. Only 2^(n-9) - 1 strings are short enough to be a ten-bit win, against 2^n inputs of length n, so under 1 in 2^9 qualify; in general, under 1 in 2^(k-1) for k bits.

solid answer

~50 s

The sharp form of the counting argument counts winners rather than merely proving one loser exists. Shrinking an `n`-bit input by at least 10 bits means landing on an output of length at most `n-10`. The number of binary strings of length at most `n-10` is `1 + 2 + ... + 2^(n-10) = 2^(n-9) - 1`, and the map is injective, so at most that many of the `2^n` inputs can win. The fraction is under `2^(n-9) / 2^n = 1/2^9`, about one input in 512, and the same count gives under `1/2^(k-1)` for a `k`-bit saving. Notice the bound does not depend on `n` at all: a bigger input does not carry more slack. Real corpora escape it only because real files sit in a tiny, highly structured corner of the input space.

code

pseudocode · 13 lines
pseudocode
# how many n-bit inputs can shrink by at least k bits?

inputs          = 2^n
short_outputs   = sum of 2^i for i = 0 .. (n - k)
                = 2^(n - k + 1) - 1

# compression is one-to-one, so winners <= short_outputs
fraction        = short_outputs / inputs
                < 2^(1 - k)
                = 1 / 2^(k - 1)

# k = 10  ->  fraction < 1 / 512
# k = 20  ->  fraction < 1 / 524288

go deeper

for a junior

Remember the shape rather than the algebra: demanding more saved bits shrinks the set of inputs that could possibly get it, and it shrinks by half for each extra bit.

for a middle

Do the count: outputs of length at most n minus k number 2^(n-k+1) minus 1, injectivity caps the winners at that, and the fraction comes out under 1 in 2^(k-1).

for a senior

Use it to size a claim rather than merely reject it, and to insist that any ratio figure names the corpus it was measured on.

for a principal

Read it as a budget: short outputs are a scarce resource spent on a chosen input population, which is exactly what a per-class compression policy allocates.

## From 'some input loses' to 'almost every input loses' The plain pigeonhole statement is weak-sounding: among the `2^n` inputs of length `n`, at least one cannot shrink, because only `2^n - 1` shorter strings exist. A margin of one invites the reply 'so it fails on a handful of inputs, who cares'. Counting the **winners** instead turns the same argument into something much stronger, and it is the version worth carrying into a review. ## The count, step by step Ask how many inputs can shrink by at least `k` bits, meaning the output has length at most `n - k`. 1. An input wins only if its output is one of the strings of length at most `n - k`. 2. Those strings number `1 + 2 + 4 + ... + 2^(n-k) = 2^(n-k+1) - 1`. 3. Compression is injective, so no two winners share an output: the number of winners is at most the number of available short strings. 4. The fraction of the `2^n` inputs that can win is therefore below `2^(n-k+1) / 2^n = 2^(1-k) = 1 / 2^(k-1)`. | Bits saved, k | Short-enough outputs | Fraction of inputs that can win | Reading | |---|---|---|---| | 1 | 2^n - 1 | under 1 | almost everything might save a single bit | | 4 | 2^(n-3) - 1 | under 1 in 8 | a nibble's saving is already a minority | | 10 | 2^(n-9) - 1 | under 1 in 512 | barely a byte of saving, and 99.8% cannot get it | | 20 | 2^(n-19) - 1 | under 1 in 524,288 | two and a half bytes is a one-in-half-a-million event | The bound halves with every extra bit demanded, which is why 'shrinks everything by even a little' collapses so fast. Halving a 1,000-bit input means `k = 500`, available to under one input in `2^499`. ## The thing people misread - **The fraction does not depend on `n`.** Bigger inputs are not looser; `2^(1-k)` has no `n` in it. Intuition says a megabyte has more slack than a kilobyte, and for *real* megabytes it usually does, but that is a fact about real data, never about the space of all inputs. - **Count outputs of length at most `n-k`, not exactly `n-k`.** Forgetting the shorter ones is the usual slip, and it changes the answer by a factor of two. - **The bound is an upper limit on winners, not a prediction.** A scheme may do far worse than the bound on a given corpus; it can never do better. - **It is a statement about the whole input space.** It is not contradicted by a benchmark where everything shrank. ## Why real archives still average large savings The files anyone actually stores are not drawn uniformly from all `2^n` strings. They are outputs of processes with heavy structure: repeated field names, aligned records, long runs, a small effective alphabet, text in one language, numbers in narrow ranges. That population is an unimaginably small subset of the input space, and a coder is engineered to spend the short outputs precisely on it. Both facts are true at once: - Almost no inputs, counted over the whole space, can shrink meaningfully. - Almost every input anyone stores does shrink meaningfully. There is no tension. The coder has chosen where to spend its short outputs, and the inputs nobody stores pay for it. That is the counting bound not as an obstacle but as a design budget. ## Where the number earns its keep In a review, the sharp form answers a claim that the plain form cannot. 'Guaranteed 20% smaller on any input' is refuted by the plain argument, but so is 'guaranteed one byte smaller on any input', and the sharp form tells you how far the second claim is from reality: an eight-bit saving is available to under one input in 128. It also gives the right question for any ratio claim, which is always *on which corpus*, since a ratio without a population named is not a claim that can be checked. And it explains why the interesting engineering question is never 'how do we shrink everything' but 'which inputs are worth spending short outputs on, and what do we do with the rest' — which is what block-level fallbacks and per-class compression policies exist to answer.

  • Why does the fraction stay the same as the input length grows?
    Because both sides scale together: demanding `k` bits leaves about `2^(n-k+1)` usable outputs against `2^n` inputs, and the `n` cancels. Larger real files do compress better, but that comes from more exploitable structure in real data, not from extra room in the space of all strings.
  • How is this different from the plain pigeonhole statement?
    The plain form proves at least one input fails to shrink, a margin of one. This form counts how many can succeed at a given saving and shows the fraction halving with every extra bit demanded, which is what makes 'guaranteed savings on arbitrary input' obviously hopeless rather than merely imperfect.

saying these in an interview costs you the question

  • Says roughly half of all inputs could lose ten bits
  • Thinks the fraction depends on which coder is used
  • Reads the bound as a claim about real files not compressing
  • Counts only outputs of length exactly n minus k
  • Assumes a larger input length loosens the bound