Rubí
Rev 3, 55bytes
i=1
'S, OJ1*$HCH(#%0'.bytes{|e|puts "%x"%i+=e*130&9011}
Como desarrollo adicional de la idea de Randomra, considere la tabla de resultados y diferencias a continuación. La tabla de diferencias se puede comprimir como antes y expandirse multiplicando por 65 = binario 1000001 y aplicando una máscara 11001100110011. Sin embargo, Ruby no funciona de manera predecible con caracteres de 8 bits (tiende a interpretarlos como Unicode).
Sorprendentemente, la última columna es completamente uniforme. Debido a esto, en compresión podemos realizar un desplazamiento de derechos sobre los datos. Esto garantiza que todos los códigos sean ASCII de 7 bits. En expansión, simplemente multiplicamos por 65 * 2 = 130 en lugar de 65.
La primera columna también es completamente uniforme. Por lo tanto, podemos agregar 1 a cada elemento (32 a cada byte) cuando sea necesario, para evitar cualquier carácter de control. El 1 no deseado se elimina utilizando la máscara 10001100110011 = 9011 en lugar de 11001100110011.
Solution 59 of document linked in question
Start0001
Out Diff
2223 2222
2433 0210
2433 0000
4445 2012
6555 2110
6577 0022
6687 0110
6887 0200
8897 2010
aa99 2202
caa9 2010
cab9 0010
cbbb 0102
cdbd 0202
cddd 0020
Aunque uso 15 bytes para la tabla, solo uso 6 bits de cada byte, que es un total de 90 bits. De hecho, solo hay 36 valores posibles para cada byte, que son 2.21E23 en total. Eso encajaría en 77 bits de entropía.
Rev 2, 58 bytes, usando el enfoque incremental de Randomra
i=0
'UPEIP@bPHPBETTEPRADT'.bytes{|e|puts "%x"%i+=e*65&819}
Finalmente, algo más corto que la solución ingenua. Enfoque incremental de Randomra, con el método bytepacking de Rev 1.
Rev 1, 72 bytes, versión golfizada de rev 0
Se hicieron algunos cambios en la línea de base para acomodar un reordenamiento del código por razones de golf, pero aún así llegó más tiempo que la solución ingenua.
i=0
'UPUIYD&!)$&V*).);c+*'.bytes{|e|i+=1;puts "%x"%(i/2*273+(e*65&819))}
Los desplazamientos se codifican en cada carácter de la cadena mágica en formato base 4 BAC
, es decir, con los 1 que representan el símbolo de la derecha, los 16 que representan el símbolo del medio y el símbolo de la izquierda en la posición del 4. Para extraerlos, el código ASCII se multiplica por 65 (binario 1000001) para dar BACBAC
, luego se suma con 819 (binario 1100110011) para dar.A.B.C
.
Algunos de los códigos ASCII tienen el conjunto de 7 bits, es decir, son 64 más altos que el valor requerido, para evitar caracteres de control. Debido a que este bit es eliminado por la máscara 819, esto es intrascendente, excepto cuando el valor de C
es 3, lo que provoca un arrastre. Esto debe corregirse solo en un lugar (en lugar de g
usarlo c
).
Rev 0, versión sin golf
a= %w{000 010 000 201 100 100 011 021 110 120 011 112 111 221 211 221 122 123 112 222}
i=2
a.each{|e|puts "%x"%(i/2*273+e.to_i(16));i+=1}
Salida
111
121
222
423
433
433
455
465
665
675
677
778
888
998
a99
aa9
abb
abc
bbc
ccc
Explicación
De la siguiente solución, resta la línea base, dando el desplazamiento que almaceno como datos. La línea base se regenera como un número hexadecimal en el código por i/2*273
(273 decimal = 111 hexadecimal).
solution baseline offset
AAA AAA 000
ABA AAA 010
BBB BBB 000
DBC BBB 201
DCC CCC 100
DCC CCC 100
DEE DDD 011
DFE DDD 021
FFE EEE 110
FGE EEE 120
FGG FFF 011
GGH FFF 112
HHH GGG 111
IIH GGG 221
JII HHH 211
JJI HHH 221
JKK III 122
JKL III 123
KKL JJJ 112
LLL JJJ 222