Haskell, 76 characters
import Bits
z a=170-sum[a.&.p*p|p<-[1,2,4,8]]
y a=[z a,z$a`div`16]
m=(>>=y)
Test runs:
> testAll
input [10, 02]
encoded [AA, A9, A6, AA]
pass
input [FF, 00, AA, 55]
encoded [55, 55, AA, AA, 66, 66, 99, 99]
pass
input [12, 34, 56, 78, 90]
encoded [A6, A9, 9A, A5, 96, 99, 6A, 95, AA, 69]
pass
input [01, 02, 03, F1, F2, F3]
encoded [A9, AA, A6, AA, A5, AA, A9, 55, A6, 55, A5, 55]
pass
Performance is well within spec. at 1MB in ~1.2s on my oldish laptop. It suffers because the input is convert to and from a list, rather then processed as a ByteArray
.
> dd bs=1m count=1 if=/dev/urandom | time ./2040-Manchester > /dev/null
1+0 records in
1+0 records out
1048576 bytes transferred in 1.339130 secs (783028 bytes/sec)
1.20 real 1.18 user 0.01 sys
The source, 2040-Manchester.hs, includes the code, tests, and main function for a command line filter.