Objectif
Créez un programme ou une paire de programmes qui perturbent et corrigent collectivement les fichiers dans le but d'empêcher LZMA2 de fonctionner efficacement. Les routines de perturbation et de correction doivent être réciproques, afin que vous puissiez récupérer le fichier d'origine exactement.
Cibles
- Les œuvres collectées de Shakespeare en plaine UTF-8 (5 589 891 octets)
- Wikimedia Commons 2013 Image de l'année en pleine résolution (1 659 847 octets)
Méthodes de compression
- Ubuntu / liés:
xz -kz5 <infile>
- Les fenêtres:
7z.exe a -txz -mx5 <outfile> <infile>
- Autre: Utilisez un compresseur LZMA2 avec un niveau de compression 5 qui comprime les œuvres de Shakespeare à 1570550 octets ± 100 octets.
Notation; somme de (tout est en octets, ls -l
ou dir
ça):
- Taille du ou des programmes (tout ce qu'il faut collectivement pour "casser" / réparer le fichier de manière réversible)
- Différence de taille (absolue) entre:
- Oeuvres brutes collectées de Shakespeare et votre copie modifiée (non compressée).
- Photo brute et votre copie modifiée (non compressée).
- Différence de taille ou 0, la valeur la plus élevée étant retenue:
- Œuvres brutes collectées de Shakespeare moins votre copie compressée LZMA2 modifiée.
- Photo brute moins votre copie compressée LZMA2 modifiée.
Exemple
Exemple de Python 2.x mal marqué, paresseusement joué, mais conforme:
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)
Fonctionnement...
$ 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
But
- = 194 + abs (5589891 - 5589891) + max (5589891 - 3014136, 0) + abs (1659874 - 1659874) + max (1659874 - 1646556, 0)
- = 194 + 0 + 2575755 + 0 + 13318
- 2 589 267 octets. Mauvais, mais ne rien faire dans les fichiers donne un score de 4 635 153 octets.
Clarification
C'est le golf, donc vous essayez de minimiser votre score. Je ne sais pas si les commentaires indiquent un trou légitime dans mon score ou s'ils le sont parce que je l'ai rendu trop compliqué. Dans tous les cas, vous voulez le PLUS PETIT :
- code source
- différence entre le fichier modifié non compressé et le fichier d'origine (par exemple, si vous le modifiez en ajoutant un billion de 0 à la fin, votre score a augmenté d'un billion d'octets)
- différence entre le fichier modifié compressé et le fichier d'origine (par exemple, plus les fichiers sont incompressibles, plus votre score est élevé). Un fichier parfaitement incompressible qui croît légèrement ou pas du tout donnera 0.
code-challenge
compression
Nick T
la source
la source
Réponses:
Python, score = 120
Crée un pad unique en utilisant md5 en mode compteur . xors le fichier avec. Cela présente l'avantage que les fichiers d'origine et perturbés sont de la même taille et que le perturbateur et le fixateur sont le même programme.
Les fichiers perturbés compressés sont plus volumineux que les originaux.
la source
C, 51 = 51 + 0 + 0 + 0 + 0
Sous les astuces de golf , ce programme boucle pour chaque octet en entrée standard, et fait exclusif ou avec un pad infini de rand (). J'ai testé cela avec rand () dans la libc d'OpenBSD 5.5.
Usage:
Pour tester mon programme, j'ai écrit un script shell test.sh (57 lignes) pour compiler mon programme et calculer mon score.
Notes sur rand () et le décalage à droite
Aucun algorithme de compression ne peut compresser des données aléatoires. Je peux déguiser pg100.txt et filament.jpg en données aléatoires si je les brouille avec un chiffrement de flux .
Ma première idée a été d' exclure du texte en clair ou en clair avec pad pour créer du texte chiffré , puis de stocker à la fois le texte chiffré et le pad dans le fichier brouillé. Cela augmenterait la taille du fichier et augmenterait mon score. Le choix évident est d'utiliser le même pad pour chaque fichier et de ne stocker que du texte chiffré dans le fichier brouillé. Si j'appelle simplement rand (), il utilise une valeur par défaut de 1 et crée le même pad à chaque fois.
OpenBSD 5.5 définit rand () dans stdlib.h et rand.c :
Il s'agit d'un générateur congruentiel linéaire . Le gros défaut est que les bits bas ont de courtes périodes. Le 1er bit a une période de 2: si vous lancez une pièce avec
rand()&1
, elle irait des têtes, des queues, des têtes, des queues, etc. Le nième bit a une période de 2 n . Il y a 31 bits, donc toute la séquence a une période de 2 31 .LZMA2 peut trouver des modèles sur de courtes périodes et les compresser. Le code le plus court
~c^rand()
prend les 8 bits les plus faibles et n'empêche pas la compression. Le bon changement dans l'~c^rand()>>9
aide, mais pas assez. J'utilise~c^rand()>>23
.~c
SCORE: 4227957 = 40 + 0 + 0 + 4019391 + 208526~c^rand()
SCORE: 2474616 = 47 + 0 + 0 + 2463735 + 10834~c^rand()>>9
SCORE: 350717 = 50 + 0 + 0 + 350667 + 0~c^rand()>>23
SCORE: 51 = 51 + 0 + 0 + 0 + 0la source
BrainFuck : 129 (129 + 0 + 0 + 0 + 0) *
random.bf (sauts de ligne ajoutés pour plus de lisibilité)
Pour créer,
unrandom.bf
vous devez changer le dernier + dans la deuxième ligne.La plupart du code est basé sur le générateur de nombres aléatoires basé sur la règle 30 de Daniel B Cristofani, adapté pour ajouter le numéro à chaque entrée et pour se terminer lorsqu'il n'y a plus d'entrée.
* J'ai testé les octets qu'il a traités jusqu'à présent 212992 (traités après 12 heures) et les deux fichiers se transforment en un fichier compressé 213064. Je suppose que cela pourrait être fait d'ici la fin de la semaine pour être sûr, mais je ne veux pas attendre la publication. Je mettrai à jour le score si c'est faux, mais gardez la solution car Rule30 bascule!
Anecdote: la règle 30 a été découverte par Stephen Wolfram en 1983 et selon Wikipedia, elle est utilisée pour produire des nombres entiers aléatoires dans Mathematica.
Compilation et exécution:
Il utilise du temps et de l'espace exponentiels (itère plus de 32 cellules supplémentaires par caractère traité), il nécessite donc un runtime BrainFuck qui a au moins 178 876 517 cellules pour coder le fichier Shakespear, ne traite pas non ascii comme unicode, possède des cellules de plus de 8 bits et utilise -1 en eof (à différer entre 255 et -1). J'utilise généralement des interprètes d'autres personnes mais cette fois, je dois être un plugin et promouvoir le mien:
jitfb compile BrainFuck en C optimisé et abuse de perl Inline :: C pour l'exécuter. Ce sont des bundles avec mon compilateur Extended BrainFuck . Avec la taille et la largeur de la cellule dans l'argument, il allouera environ 400 Mo.
la source
CJam, 22 octets
Cela utilise un générateur de Fibonacci décalé avec une relation de récurrence s n = (s n-5 + s n-16 )% 255 (que j'ai sélectionné par erreur, mais cela fonctionne quand même) et une graine triviale pour générer un flux pseudo-aléatoire d'octets , qu'il XORs ensuite avec l'entrée.
J'ai testé mon code avec CJam 0.6 , qui a été publié le 1er mai 2014.
Comment ça fonctionne
But
la source
PHP, 117 + 0 + 0 + 0 + 0 = 117
Parce que confieriez-vous vraiment la tâche de falsifier vos données au-delà de la reconnaissance à une autre langue?
Alors que toutes les autres solutions sont basées sur des constructions «sécurisées» comme des «générateurs de nombres aléatoires» ou une «cryptographie de qualité militaire», celle-ci interprète simplement les chaînes comme représentant des nombres impairs de longueur modulo 2⋅256 ^ et calcule leur inverse modulaire .
Démo:
la source
script shell, 203
L'exécuter:
Pas très portable, mais pourrait être fait au prix de quelques octets. Nécessite PGP (une implémentation avec OpenSSL serait également possible). La différence de ~ 50 octets entre le fichier encodé et l'original peut probablement être enregistrée.
Notation:
84 + abs (1659874 - 1659943) + max (1659874 - 1660084, 0) + abs (5589891 - 5589941) + max (5589891 - 5590284, 0) = 203
la source
Python, score = 183 + 7 + 6 + 0 + 0 = 196
La notation vous pénalise pour avoir rendu le fichier complètement incompressible, car le fichier compressé est plus volumineux par rapport à la surcharge de compression. Ainsi, mon programme les rend légèrement moins que totalement incompressibles:
Résultat:
la source