Citable writeup. The language-revised note is explainer.pdf (Stephen Wu, 16 August 2026, language revised 24 August 2026). This page is an older interactive companion.

Covering codes · 10 rows · radius 2

50 columns
cover 1024
syndromes

The best published length is 51 columns, unchanged since 2003. This page defines the problem, presents a 50-column matrix, and explains why the entry at redundancy 10 controls an infinite family.

Part 1 · Codes

Two different jobs a code can do

A computer stores data as strings of bits. A string of length n is a list of n zeros and ones. Noise flips some of those bits.

A code is a chosen subset of all the possible strings. We call the chosen strings codewords. You send only codewords. If noise flips a few bits, the result is usually not a codeword. The receiver then looks for the nearest codeword.

Distance

The distance between two bit strings is the number of positions where they differ. For example, 10110 and 10011 differ in positions 3 and 4, so their distance is 2.

A code is designed for one of two opposite jobs.

The first job is error correction. Here you want the codewords far apart. If every pair of codewords has distance 5 or more, you can repair up to 2 flipped bits without any doubt. This is the packing problem. It asks you to pack many balls into the space without overlap.

The second job is covering. Here you want every string in the whole space to sit close to some codeword. No string is allowed to be far from everything. This page is about the second job only.

Covering radius

The covering radius of a code is the largest distance from any string to its nearest codeword. A covering radius of 2 means this: you can reach a codeword from any string in at most 2 bit flips.

Covering codes are useful because they let you round. Take any string, move to the nearest codeword, and store the codeword instead. You lose at most 2 bits of accuracy. That idea appears in data compression, in steganography, and in the football pool problem, which asks how few betting slips guarantee a near-win.

The interesting question is cost. Codewords are cheap to store when there are few of them, but few codewords leave big gaps. So we ask a minimum question. How short can a code be and still have covering radius 2?

Part 2 · Syndromes

Why the whole problem fits in 1024 numbers

The question above involves 2ⁿ strings. That is far too many to search. The problem gets much smaller once we restrict to linear codes.

Linear code

A code is linear when the XOR of any two codewords is again a codeword. XOR means bit-by-bit addition where 1 + 1 = 0. It is ordinary addition modulo 2.

A linear code has a compact description. You write down a matrix H with r rows and n columns, filled with zeros and ones. A string x is a codeword exactly when Hx = 0, computed modulo 2. We call r the redundancy. The code then has 2ⁿ⁻ʳ codewords.

Syndrome

The syndrome of a string x is the vector s = Hx, computed modulo 2. It has r bits, so there are 2ʳ possible syndromes. A string is a codeword exactly when its syndrome is zero.

Now comes the step that makes the problem finite. Flip bit i of a string. The syndrome changes by exactly column i of H. Flip two bits, and the syndrome changes by the XOR of those two columns.

So the distance from x to the nearest codeword is the smallest number of columns that XOR to the syndrome of x. This gives the whole problem in one line. Write S for the set of columns of H.

{0}  ∪  S  ∪  (S + S)  =  all 2r syndromes Covering radius 2 means every syndrome is zero, or a column, or the XOR of two columns.

Set r = 10. There are 1024 syndromes. The columns are themselves 10-bit numbers, so they live in the same set of 1024 values. The problem is now completely concrete.

Choose as few 10-bit numbers as you can, so that their pairwise XORs reach all 1024 values.

The example below uses the actual matrix. It shows a syndrome that needs two flips, and which two.

Correcting a word whose syndrome is 8 s = 8 = 0000001000 ← the syndrome of some received word x
8 is not a column of H, so one bit flip cannot reach it.

column 21 = 373 = 0101110101
column 22 = 381 = 0101111101
XOR               0000001000 = 8  ✓

Flip bits 21 and 22 of x. The new syndrome is 0, so the result is a codeword.
Distance from x to the code = 2.
The length function

Write ℓ₂(r,R) for the shortest length of a binary linear code with redundancy r and covering radius R. The subject of this page is ℓ₂(10,2).

Part 3 · The search

A counting bound gives 45. The published record is 51.

Start with a count. Take n columns. Then you get one empty sum, n single columns, and n(n−1)/2 pairs. Together they give

1 + n + n(n−1)/2  ≥  1024 You need at least this many representations to have any chance of covering 1024 syndromes.

Solve it and you get n ≥ 45. This is the sphere-covering bound. No known code at r = 10 reaches it.

The count is optimistic because it assumes no two pairs collide. Real column sets collide constantly. In the 50-column matrix on this page, the 1225 pairs produce only 986 distinct results. That means 239 pairs land on a value another pair already reached. Each collision wastes one representation.

So the true answer sits above 45, and finding it is hard. Kaikkonen and Rosendahl published a 51-column matrix in 2003. That has stayed the shortest published answer for over twenty years. A search run in 2026 found a 50-column matrix. The map below is that matrix.

50columns
1024syndromes reached
0missed
1.246reps per syndrome
zero, needs no columns
is itself a column
exactly one pair reaches it
six pairs reach it
nothing reaches it
Each cell is one of the 1024 syndromes. Brighter blue means more pairs reach it.

Point at a cell to see how the columns reach it.
Click a column to remove it. The map stays dark because most syndromes have exactly one representation.

The map is mostly dark. Of the 973 syndromes that need a pair, 821 have exactly one pair that reaches them. The matrix has almost no spare capacity.

You can test this directly. Remove any single column and the map breaks. The least damaging choice still leaves 9 syndromes with nothing reaching them. Try the button and see.

A set that breaks when you remove any one element is called minimal. In the geometric language of this field, these 50 columns form a minimal 1-saturating set in the projective space PG(9,2). No deletion shortens this matrix.

How the search ran

The start was the published 51-column matrix. Among its 51 single deletions, removing the column stored as the integer 419 leaves 11 of the 1024 syndromes unreached, the fewest possible. That 50-column set was the seed.

The search keeps exactly 50 distinct nonzero columns at all times and scores a position by counting the syndromes that nothing reaches. A table of 1024 counters makes the score cheap to maintain. Swapping one column only touches its own counter and the 49 pair sums that involve it, about 100 updates instead of recounting all 1276 sums.

Most moves aim at a hole. Pick an unreached syndrome g, then offer g itself as a new column, or g XOR s for a current column s, so the swap covers the hole at once. One uniformly chosen column is deleted in exchange. Simulated annealing decides acceptance. Improvements always pass. Uphill steps pass with a probability that shrinks as the temperature falls from 3.5 to 0.05 across each cycle of 80,000 proposals. At the end of a cycle the search resets to the best state seen so far.

The random numbers come from a fixed xorshift64 seed, so the whole run replays exactly. Run 0 reached zero holes at proposal 3,600,281, a few hundred proposals after its 45th reset. The final matrix keeps 35 of the 50 seed columns. The committed script compute/search_radius2.py replays the run.

The same method failed on three nearby gaps. It missed 3 of 256 syndromes at redundancy 8. At redundancy 9, every single deletion from the published 39-column set left at least 8 of 512 unreached. With 49 columns at redundancy 10 it stalled at 7 of 1024. Exact solvers returned no verdict either way. Those numbers say where the search stopped, not what is impossible.

Part 4 · The seed

Why one column matters

The step from 51 to 50 looks small. Its effect is larger, because the published table is built by iteration.

Davydov, Marcugini and Pambianco published the current best bounds in November 2025. Their tables list a value for every redundancy r up to 64. They do not find each value separately. A construction they call QM₂² produces a long code from a short one.

nnew = 2m(nold + 1) − 1     rnew = rold + 2m Apply this repeatedly and one short code produces an infinite family of longer ones.

Their radius-2 family iterates from a single starting point, the 51-column matrix at r = 10. Their own proof calls the structure of that matrix "very important for the next iterative process."

So the entry at r = 10 controls the family. Improve it by one column and every entry produced from it improves. The limit that the family approaches improves as well.

Part 5 · Blocks

A shorter matrix is not enough

The growth construction needs a second thing from its starting matrix. It needs a way to sort the columns into blocks.

Valid block split

Sort the columns into blocks. The split is valid when every syndrome still has a representation that uses columns from different blocks. Write p(H) for the number of blocks. The paper calls a valid split a (2,0)-partition.

The number of blocks controls how much you can grow the code in one step. The construction requires p(H) ≤ 2ᵐ ≤ n. Fewer blocks means larger steps are legal.

The published 51-column matrix needs 11 blocks. The 50-column matrix accepts 10. That is both smaller and safely under the 16 that the first growth step requires.

Finding the split is a constrained graph coloring problem. The 821 syndromes with exactly one pair force those two columns into different blocks, which produces a graph with 821 edges. The other 152 syndromes are less constrained. Each one only needs one of its 2 to 6 pairs split across blocks.

A separate search on the same day found the split. That search code is not in the repository. The repository keeps the split itself as data, plus two independent verifiers, in two languages, that re-derive the columns from the matrix text and verify all 1024 syndromes. The block labels are the only thing read from the data file. Nobody has shown that 10 blocks is the fewest possible.

The matrix also has a third property that later growth steps need. It has exactly ten triples of columns that XOR to zero. Exactly one of them has its three columns in three different blocks.

Part 6 · Growth

What the new seed produces

Apply the published construction to the 50-column matrix. Take m = 4, then m = 5. Then verify the results by enumerating every syndrome, with no sampling.

redundancynew lengthpublishedreps per syndromechecked
1050511.246091024 of 1024
188158311.26847262,144 of 262,144
20163116631.269241,048,576 of 1,048,576
2t51·2t−5 − 126·2t−4 − 1→ 1.27002by construction

The fourth column of that table has a name. It is the covering density: the total number of representations divided by the number of syndromes. It is the average number of ways each syndrome gets reached. It can never drop below 1. A value near 1 means an efficient code.

As redundancy grows, this family drives the density toward 2601/2048 ≈ 1.27002. Compare that to the record before it.

Best density that a known family approaches. Lower is better
1.42381992
1.3203Nov 2025
1.2700this seed

The step on the right is bigger than the step on the left. The 2025 paper moved a number that had stood for 33 years. Reseeding it with one fewer column moves it further.

Part 7 · Limits

What this does not prove

Search and proof are separate

The search only had to succeed once. The proof does not use it. The claim is a finite statement about 500 committed bits.

Two independent programs verify that statement in about two seconds. They read the matrix from text and do not trust the search or its author.