Objetivo
Cree un programa o un par de programas que interrumpan y arreglen colectivamente archivos con la intención de evitar que LZMA2 funcione de manera efectiva. Las rutinas de interrupción y reparación deben ser recíprocas, para que pueda recuperar el archivo original exactamente.
Objetivos
- Las obras recopiladas de Shakespeare en UTF-8 simple (5,589,891 bytes)
- Imagen del año de Wikimedia Commons 2013 en resolución completa (1,659,847 bytes)
Métodos de compresión
- Ubuntu / relacionado:
xz -kz5 <infile>
- Ventanas:
7z.exe a -txz -mx5 <outfile> <infile>
- Otro: Use un compresor LZMA2 con nivel de compresión 5 que comprima las obras de Shakespeare a 1570550 bytes ± 100 bytes.
Puntuación; suma de (todo está en bytes ls -l
o dir
):
- Tamaño del programa (s) (lo que sea necesario colectivamente para "romper" / arreglar el archivo de forma reversible)
- Diferencia de tamaño (absoluto) entre:
- Obras recopiladas sin procesar de Shakespeare y su copia modificada (sin comprimir).
- Foto sin procesar y su copia modificada (sin comprimir).
- Diferencia de tamaño o 0, lo que sea mayor entre:
- Trabajos recopilados sin procesar de Shakespeare menos su copia comprimida LZMA2 modificada.
- Foto sin procesar menos su copia comprimida LZMA2 modificada.
Ejemplo
Ejemplo de Python 2.x mal puntuado, perezosamente golfizado, pero compatible:
import sys
x = 7919 if sys.argv[1] == 'b' else -7919
i = bytearray(open(sys.argv[2], 'rb').read())
for n in range(len(i)):
i[n] = (i[n] + x*n) % 256
o = open(sys.argv[2]+'~', 'wb').write(i)
Corriendo...
$ python break.py b pg100.txt
$ python break.py f pg100.txt~
$ diff -s pg100.txt pg100.txt~~
Files pg100.txt and pg100.txt~~ are identical
$ python break.py b Glühwendel_brennt_durch.jpg
$ python break.py f Glühwendel_brennt_durch.jpg~
$ diff -s Glühwendel_brennt_durch.jpg Glühwendel_brennt_durch.jpg~~
Files Glühwendel_brennt_durch.jpg and Glühwendel_brennt_durch.jpg~~ are identical
$ xz -kz5 pg100.txt~
$ xz -kz5 Glühwendel_brennt_durch.jpg~
$ ls -ln
-rw-rw-r-- 1 2092 2092 194 May 23 17:37 break.py
-rw-rw-r-- 1 2092 2092 1659874 May 23 16:20 Glühwendel_brennt_durch.jpg
-rw-rw-r-- 1 2092 2092 1659874 May 23 17:39 Glühwendel_brennt_durch.jpg~
-rw-rw-r-- 1 2092 2092 1659874 May 23 17:39 Glühwendel_brennt_durch.jpg~~
-rw-rw-r-- 1 2092 2092 1646556 May 23 17:39 Glühwendel_brennt_durch.jpg~.xz
-rw-rw-r-- 1 2092 2092 5589891 May 23 17:24 pg100.txt
-rw-rw-r-- 1 2092 2092 5589891 May 23 17:39 pg100.txt~
-rw-rw-r-- 1 2092 2092 5589891 May 23 17:39 pg100.txt~~
-rw-rw-r-- 1 2092 2092 3014136 May 23 17:39 pg100.txt~.xz
Puntuación
- = 194 + abs (5589891 - 5589891) + max (5589891 - 3014136, 0) + abs (1659874 - 1659874) + max (1659874 - 1646556, 0)
- = 194 + 0 + 2575755 + 0 + 13318
- 2,589,267 bytes. Malo, pero no hacer nada a los archivos produce una puntuación de 4,635,153 bytes.
Aclaración
Esto es golf, por lo que está tratando de minimizar su puntaje. No estoy seguro de si los comentarios señalan un agujero legítimo en mi puntuación o si lo son porque lo hice demasiado complicado. En cualquier caso, quieres lo MÁS PEQUEÑO :
- código fuente
- diferencia entre el archivo modificado sin comprimir y el archivo original (por ejemplo, si lo modifica agregando un billón de ceros al final, su puntaje subió un billón de bytes)
- diferencia entre el archivo modificado comprimido y el archivo original (por ejemplo, cuanto más incompresibles sean los archivos, mayor será su puntaje). Un archivo perfectamente incompresible que crezca ligeramente o no se puntuará 0.
code-challenge
compression
Nick T
fuente
fuente
Respuestas:
Python, puntuación = 120
Hace un pad de una sola vez usando md5 en modo contador . Xors el archivo con él. Esto tiene la ventaja de que los archivos originales e interrumpidos son del mismo tamaño, y que el disruptor y el fijador son el mismo programa.
Los archivos interrumpidos comprimidos son más grandes que los originales.
fuente
C, 51 = 51 + 0 + 0 + 0 + 0
Bajo los trucos de golf , este programa realiza un bucle para cada byte en la entrada estándar, y lo hace de forma exclusiva o con un pad infinito de rand (). Probé esto con rand () en libc de OpenBSD 5.5.
Uso:
Para probar mi programa, escribí un script de shell test.sh (57 líneas) para compilar mi programa y calcular mi puntaje.
Notas sobre rand () y el desplazamiento a la derecha
Cualquier algoritmo de compresión no puede comprimir datos aleatorios. Puedo disfrazar pg100.txt y filament.jpg como datos aleatorios si los codifico con un cifrado de flujo .
Mi primera idea fue hacer un texto exclusivo o simple con el teclado para crear texto cifrado , luego almacenar el texto cifrado y el teclado en el archivo codificado. Esto aumentaría el tamaño del archivo y aumentaría mi puntaje. La opción obvia es usar el mismo pad para cada archivo y almacenar solo texto cifrado en el archivo codificado. Si solo llamo a rand (), usa una semilla predeterminada de 1 y hace el mismo pad cada vez.
OpenBSD 5.5 define rand () en stdlib.h y rand.c :
Este es un generador congruencial lineal . El gran defecto es que los bits bajos tienen períodos cortos. El primer bit tiene un período de 2: si lanzas una moneda
rand()&1
, iría cara , cruz, cara, cruz, etc. El enésimo bit tiene un período de 2 n . Hay 31 bits, por lo que toda la secuencia tiene un período de 2 31 .LZMA2 puede encontrar patrones en períodos cortos y comprimirlos. El código más corto
~c^rand()
toma los 8 bits bajos y no impide la compresión. El cambio correcto en~c^rand()>>9
ayuda, pero no lo suficiente. Yo uso~c^rand()>>23
.~c
PUNTUACIÓN: 4227957 = 40 + 0 + 0 + 4019391 + 208526~c^rand()
PUNTUACIÓN: 2474616 = 47 + 0 + 0 + 2463735 + 10834~c^rand()>>9
PUNTUACIÓN: 350717 = 50 + 0 + 0 + 350667 + 0~c^rand()>>23
PUNTUACIÓN: 51 = 51 + 0 + 0 + 0 + 0fuente
BrainFuck : 129 (129 + 0 + 0 + 0 + 0) *
random.bf (avances de línea añadidos para facilitar la lectura)
Para crear
unrandom.bf
necesita cambiar el último + en la segunda línea.La mayor parte del código se basa en el generador de números aleatorios basado en la Regla 30 de Daniel B Cristofani adaptado para agregar el número a cada entrada y para terminar cuando no hay más entrada.
* He probado los bytes que ha procesado hasta ahora 212992 (procesados después de 12 horas) y ambos archivos se convierten en un archivo comprimido 213064. Supongo que podría hacerse antes de fin de semana para saberlo con certeza, pero no quiero esperar con la publicación. Actualizaré el puntaje si está mal, ¡pero mantén la solución ya que Rule30 es genial!
Curiosidades: Stephen Wolfram descubrió la Regla 30 en 1983 y, según Wikipedia, se usa para producir enteros aleatorios en Mathematica.
Compilación y ejecución:
Utiliza tiempo y espacio exponenciales (itera más de 32 celdas más por char procesado), por lo que requiere un tiempo de ejecución BrainFuck que tiene al menos 178,876,517 celdas para codificar el archivo Shakespear, no trate los no ascii como unicode, tiene celdas más anchas de 8 bits y usa -1 como eof (para diferir entre 255 y -1). Usualmente uso intérpretes de otras personas, pero esta vez necesito ser un complemento y promover el mío:
jitfb compila BrainFuck para C optimizado y abusa de Perl Inline :: C para ejecutarlo. Se incluye con mi compilador Extended BrainFuck . Con el tamaño y el ancho de la celda en el argumento, asignará aproximadamente 400 MB.
fuente
CJam, 22 bytes
Esto utiliza un generador de Fibonacci rezagado con relación de recurrencia s n = (s n-5 + s n-16 )% 255 (que seleccioné por error, pero funciona de todos modos) y una semilla trivial para generar un flujo de bytes pseudoaleatorio , que luego XOR con la entrada.
He probado mi código con CJam 0.6 , que se publicó el 1 de mayo de 2014.
Cómo funciona
Puntuación
fuente
PHP, 117 + 0 + 0 + 0 + 0 = 117
¿Porque realmente confiaría la tarea de manipular sus datos más allá del reconocimiento a cualquier otro idioma?
Si bien todas las demás soluciones se basan en construcciones "seguras" como "generadores de números aleatorios" o "criptografía de grado militar", esta simplemente interpreta las cadenas como representantes de números impares módulo 2⋅256 ^ de longitud, y calcula su inverso modular .
Manifestación:
fuente
script de shell, 203
Ejecutándolo:
No es muy portátil, pero podría hacerse a costa de un par de bytes. Requiere PGP (también sería posible una implementación con OpenSSL). La diferencia de ~ 50 bytes entre el archivo codificado y el original probablemente se pueda guardar.
Puntuación:
84 + abs (1659874 - 1659943) + max (1659874 - 1660084, 0) + abs (5589891 - 5589941) + max (5589891 - 5590284, 0) = 203
fuente
Python, puntaje = 183 + 7 + 6 + 0 + 0 = 196
La puntuación lo penaliza por hacer que el archivo sea completamente incompresible, ya que el archivo comprimido es más grande que la sobrecarga de compresión. Por lo tanto, mi programa los hace un poco menos que totalmente incompresibles:
Resultado:
fuente