python 3.8, 161+1+287+269+6985=7702
from zlib import decompress as D
from itertools import product as P
from functools import reduce as R
x=287
d=open('f','rb').read()
print(eval(D(d[:x]))(d[x:]))
where D(d[:x])
is
(lambda f,
rest_len=[265,7,8,24,50,10,6,134,14,24,229],
genes_len=[7097,1274,276,76,223,62,122,122,420,39],
cut=lambda s,x:R(
lambda acc,n:[acc[0][n:],acc[1]+[acc[0][:n]]],
x,[s,[]])[1],
cut_out=lambda x,n:x[:n]+x[n+1:],
C=[''.join(i) for i in P('AGCU',repeat=3)]:
cut_out(''.join(i+''.join(j)
for i,j in zip(
cut(D(f[:269]).decode('utf-8'),rest_len),
cut([C[i-32] for i in D(f[269:])],genes_len)+[[]])
),13468)
)
and the file f
is here (produced with decode.py).
Posted here only to show grouping nucleotides approach as the decoder overhead is very large.
So let's start with the explanations. As can be seen form MN908947, the virus mRNA contains "head" (265 nucleotides), "tail" (229 nucleotides) and translated parts with some non-translated parts between them. So, we have 10 genes, named orf1ab, S, ORF3a, E, M, ORF6, ORF7a, ORF8, N, ORF10 in the link above.
It comes out we could use codon usage bias as the picture of frequency codon (=nucleotide triples) usage is very impressive, e.g. for orf1ab
:
or for S
(looks very similar):
and for N
(looks different):
More precisely, here's the table of normed covariance of the codon usage distributions:
orf1ab S ORF3a E M ORF6 ORF7a ORF8 N ORF10
orf1ab 1.0000 0.9243 0.7458 0.4237 0.4813 0.5143 0.6391 0.6897 0.5035 0.3201
S 0.9243 1.0000 0.7077 0.3834 0.4596 0.5266 0.6513 0.6451 0.5371 0.3519
ORF3a 0.7458 0.7077 1.0000 0.4683 0.5483 0.4119 0.5713 0.5957 0.3464 0.2862
E 0.4237 0.3834 0.4683 1.0000 0.2966 0.2057 0.4727 0.2994 0.0318 0.2621
M 0.4813 0.4596 0.5483 0.2966 1.0000 0.2495 0.3799 0.3432 0.2975 0.1776
ORF6 0.5143 0.5266 0.4119 0.2057 0.2495 1.0000 0.3737 0.3459 0.1980 0.3125
ORF7a 0.6391 0.6513 0.5713 0.4727 0.3799 0.3737 1.0000 0.5232 0.3223 0.2362
ORF8 0.6897 0.6451 0.5957 0.2994 0.3432 0.3459 0.5232 1.0000 0.2049 0.0902
N 0.5035 0.5371 0.3464 0.0318 0.2975 0.1980 0.3223 0.2049 1.0000 -0.0203
ORF10 0.3201 0.3519 0.2862 0.2621 0.1776 0.3125 0.2362 0.0902 -0.0203 1.0000
So we want to compress these genes. Here's the comparison of compression approaches:
arithm .lzma .xz zlib a.ovh len
0:orf1ab 4925.7 5261 5308 5083 86.5 7097
1:S 879.5 1047 1092 940 59.1 1274
2:ORF3a 191.4 276 324 237 37.4 276
3:E 47.8 100 132 84 18.6 76
4:M 155.4 232 280 200 35.1 223
5:ORF6 36.9 86 120 70 15.4 62
6:ORF7a 81.2 143 184 124 25.2 122
7:ORF8 80.2 144 184 122 24.2 122
8:N 289.9 393 440 338 44.1 420
9:ORF10 22.5 64 96 47 11.6 39
where arithm
is arithmetical encoding and a.ovh
is frequences compressed with fibonacci (+1 ending bit for each) -- the arithmetical encoding overhead.
We see the comparison makes zlib a perfect candidate, as even if we compress all with arithmetical encoding, we would have left something like 193 bytes for writing the decoding overhead (versus zlib), which is highly unlikely to fit in there.