What am I doing, and why does it work?
A PNG stores an image as rows, and before compressing it, it can subtract each
row from the row above — the Up filter. If you write a DNA sequence
into an image one byte per base, the width you choose decides which bases end up
stacked on top of each other.
Pick a width equal to the period of a tandem repeat and every row becomes a
copy of the row above. The subtraction leaves almost nothing, and the file
collapses. Pick any other width and it does not. The size of the file is a
measurement of the sequence's periodicity, and that is the whole game.
Two things follow, and both are levels here: every multiple of the
period snaps too, so finding 342 tells you to try 171; and the answer wanted is
always the smallest width that snaps.
Why the copies are never identical. A perfect repeat is not the
easiest case, it is an impossible one: after the row difference there is so
little left that the file is tiny at every width and nothing stands out. A few
percent of drift between copies is what gives the period something to be
measured against. Every level here carries at least 4%.
Why widths start at 20. DNA has four letters. At width 2 the row
difference is between neighbouring bases and takes a handful of values, so it
compresses brilliantly no matter what the sequence is doing — every level
"snaps" at 2, 3, 4 and so on. That is an artefact of the alphabet, not a period.
The Python version dodges it by comparing each width to a rolling local
baseline rather than to everything else; this game dodges it by not offering
those widths.
The honest part. These sequences are synthetic. On a real genome the
monomers of a satellite array differ by insertions and deletions, not only
substitutions, and a single inserted base shifts every later row out of phase —
at about 0.5% per base the signal is gone. Real arrays are handled by
compressors whose matching does not care about alignment, which are noisier.
The measurements are in experiments/ in the repository.