Стиснення LZMA2 Thwart


11

Мета

Створіть програму або пару програм, які спільно руйнують та виправляють файли з метою запобігання ефективній роботі LZMA2. Програми зриву та виправлення повинні бути взаємними, тому ви можете точно відновити вихідний файл.

Цілі

Методи стиснення

  • Ubuntu / пов'язані: xz -kz5 <infile>
  • Windows: 7z.exe a -txz -mx5 <outfile> <infile>
  • Інше: Використовуйте компресор LZMA2 з рівнем стиснення 5, який стискає роботи Шекспіра до 1570550 байт ± 100 байт.

Оцінка балів; сума (все в байтах, ls -lабо dirце):

  • Розмір програми (програм) (незалежно від того, що потрібно, щоб зворотно "зламати" / виправити файл)
  • Різниця в розмірах (абсолютна) між:
    • Сирі зібрані твори Шекспіра та Ваша модифікована (нестиснена) копія.
    • Сира фотографія та модифікована (нестиснена) копія.
  • Різниця в розмірі або 0, залежно від того, що більше між:
    • Сировинні зібрані твори Шекспіра за вирахуванням модифікованої копії, стисненої LZMA2.
    • Сира фотографія за вирахуванням модифікованої копії, стиснутої LZMA2.

Приклад

Поганий забій, ліниво гольф, але сумісний приклад Python 2.x:

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)

Працює ...

$ 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

Оцінка

  • = 194 + abs (5589891 - 5589891) + max (5589891 - 3014136, 0) + abs (1659874 - 1659874) + max (1659874 - 1646556, 0)
  • = 194 + 0 + 2575755 + 0 + 13318
  • 2589,267 байт. Погано, але нічого не робити для файлів, ви отримуєте 4,635,153 байт.

Уточнення

Це гольф, тому ви намагаєтеся мінімізувати свій рахунок. Я не впевнений, чи зазначають у коментарях законну дірку в моєму оцінці, чи вони є, тому що я зробив це занадто складно. У будь-якому випадку, ви хочете, щоб найменше :

  • вихідний код
  • різниця між нестисненим модифікованим файлом та оригінальним файлом (наприклад, якщо ви модифікуєте його, додавши трильйон 0 в кінці, ваш рахунок просто збільшився на трильйон байтів)
  • різниця між стиснутим модифікованим файлом та оригінальним файлом (наприклад, чим більше стискаються файли, тим вищий результат). Ідеально нестислимий файл, який трохи зростає або зовсім не набирає 0.

2
Відповідь тролінгу: Крок 1 - опрацюйте, скільки вільного місця у вас на диску потім розділіть на розмір файлу, щоб отримати N. Крок 2 - додайте файл до себе N разів і додайте число N. Крок 3 - зрозумійте, що є не залишається місця для стиснення файлу, але закінчується абсолютна різниця у розмірі файлів кількох терабайт (або більше) .... [Щоб повернути назад, прочитайте N з кінця файлу і зменшіть файл на 1 / N-й розмір. ]
MT0

@ MT0: Ах, я думаю, що рішення полягає в тому, що відмінності не повинні бути абсолютними. Якщо ваш змінений файл більший, він повинен відняти точки.
Клавдіу

@ MT0, якщо ви модифікуєте файл, щоб він зробив терабайт великим, то ваш бал буде 1 терабайт ... досить погано, коли ви намагаєтеся займатися гольфом.
Нік Т

@ MT0 Я додав уточнення до повідомлення, чи це допомагає?
Нік Т

2
Один каламбур. Компресор може створити більший файл, якщо t особливо нестислимий. У цьому випадку ви повинні бути винагороджені, а не покарані, ні?
Клавдіу

Відповіді:


8

Пітон, оцінка = 120

import sys,hashlib
i=0
for c in sys.stdin.read():sys.stdout.write(chr(ord(c)^ord(hashlib.md5(str(i)).digest()[0])));i+=1

Робить одноразову колодку, використовуючи md5 в режимі лічильника . xors файл з ним. Це має перевагу в тому, що оригінальні та порушені файли мають однаковий розмір, а також те, що деструктор та фіксатор - одна і та ж програма.

Стиснуті порушені файли більше, ніж оригінали.


Я налаштував забив так , якщо заархівовані файли більше , ніж їх аналоги оригінальних ви не каралися , і вони просто забити 0. Не впевнений , яким чином різниця була для ваших файлів , але ви можете оновити рахунок
Нік T

@NickT: оновлено.
Кіт Рендалл

8

C, 51 = 51 + 0 + 0 + 0 + 0

main(c){for(;c=~getchar();putchar(~c^rand()>>23));}

Під гольф-хитрості ця програма замикається на кожен байт зі стандартним входом і робить ексклюзивне - або з нескінченним майданчиком від rand (). Я перевірив це за допомогою rand () в libc OpenBSD 5.5.

Використання:

./scramble <orig >scrambled
./scramble <scrambled >orig.copy

Щоб перевірити свою програму, я написав скрипт оболонки test.sh (57 рядків), щоб скласти свою програму і обчислити міркування .

$ sh test.sh
[1/4] Compiling scramble...
/tmp//ccbcB43x.o(.text+0x6): In function `main':
: warning: rand() isn't random; consider using arc4random()
[2/4] Scrambling files...
[3/4] Compressing scrambled files...
[4/4] Checking descrambler...
SCORE: 51=51+0+0+0+0
You may wish to rm -rf tmp.9Tjw89dgCs
$ ls -l tmp.9Tjw89dgCs/
total 43032
-rw-r--r--  1 kernigh  kernigh  1659874 May 28 17:23 filament.jpg.cp
-rw-r--r--  1 kernigh  kernigh  1659874 May 28 17:23 filament.jpg.sc
-rw-r--r--  1 kernigh  kernigh  1660016 May 28 17:23 filament.jpg.sc.xz
-rw-r--r--  1 kernigh  kernigh  5589891 May 28 17:23 pg100.txt.cp
-rw-r--r--  1 kernigh  kernigh  5589891 May 28 17:23 pg100.txt.sc
-rw-r--r--  1 kernigh  kernigh  5590232 May 28 17:23 pg100.txt.sc.xz
-rwxr-xr-x  1 kernigh  kernigh     8564 May 28 17:23 scramble

Примітки про rand () та правильний зсув

Будь-який алгоритм стиснення не може стискати випадкові дані. Я можу замаскувати pg100.txt і filament.jpg як випадкові дані, якщо я їх зашифрую за допомогою шифру потоку .

Моя перша ідея полягала в тому, щоб зробити ексклюзивний чи просто текст із накладкою, щоб зробити шифротекст , а потім зберегти як шифротекст, так і килимок у зашифрованому файлі. Це збільшило б розмір файлу та збільшило мою оцінку. Очевидним вибором є використання одного і того ж майданчика для кожного файлу та збереження у шифрованому файлі лише шифротексту . Якщо я просто закликаю rand (), він використовує насіння за замовчуванням 1 і робить кожен і той самий майданчик кожен раз

OpenBSD 5.5 визначає rand () у stdlib.h та rand.c :

/* from stdlib.h */
#define RAND_MAX    0x7fffffff

/* from rand.c */
static u_int next = 1;

int
rand_r(u_int *seed)
{
    *seed = *seed * 1103515245 + 12345;
    return (*seed % ((u_int)RAND_MAX + 1));
}

int
rand(void)
{
    return (rand_r(&next));
}

Це лінійний конгрурентний генератор . Великий недолік полягає в тому, що низькі біти мають короткі періоди. Перший біт має період 2: якщо ви перевернете монету rand()&1, вона піде головами, хвостами, головами, хвостами тощо. П'ятий біт має період 2 n . Є 31 біт, тому вся послідовність має період 2 31 .

LZMA2 може знаходити візерунки в короткі періоди і стискати їх. Найкоротший код ~c^rand()займає низькі 8 біт і не запобігає стисненню. Правильна зміна ~c^rand()>>9допомагає, але недостатньо. Я використовую ~c^rand()>>23.

  • ~c ШКОЛА: 4227957 = 40 + 0 + 0 + 4019391 + 208526
  • ~c^rand() ШКОЛА: 2474616 = 47 + 0 + 0 + 2463735 + 10834
  • ~c^rand()>>9 ШКОЛА: 350717 = 50 + 0 + 0 + 350667 + 0
  • ~c^rand()>>23 ШКОЛА: 51 = 51 + 0 + 0 + 0 + 0

5

BrainFuck : 129 (129 + 0 + 0 + 0 + 0) *

random.bf (для читабельності додаються рядкові стрічки)

,+[->>>>++[<++++++++[<[<++>-]>>[>>]+>>+[-[->>+<<<[<[<<]<
+>]>[>[>>]]]<[>>[-]]>[>[-<<]>[<+<]]+<<]<[>+<-]>>-]<[-<<+
>>]<<.,+[->]>>>]]

Для створення unrandom.bfвам потрібно змінити останній + у другому рядку.

Більшість кодів заснований на генераторі випадкових чисел на основі Правила 30 Даніеля Кристофані, пристосованому для додавання числа до кожного вводу та припинення, коли більше немає вводу.

* Я перевірив оброблені до цього часу байти 212992 (обробляється через 12 годин), і обидва файли перетворюються на стислий файл 213064. Я думаю, це може бути зроблено до кінця тижня напевно, але я не хочу чекати з публікацією. Я оновлю оцінку, якщо вона неправильна, але зберігайте рішення, оскільки Rule30 скалює!

Дрібниці: Правило 30 було відкрито Стівеном Вольфрамом у 1983 році, і згідно Вікіпедії воно використовується для отримання випадкових цілих чисел у Mathematica.

Компіляція та запуск:

Він використовує експоненціальний час та простір (ітератує більше 32 осередків на оброблювану таблицю), тому для кодування файлу Шекспіра потрібен час виконання BrainFuck, який має принаймні 178 876 557 комірок, не трактує non ascii як unicode, має ширше 8 біт комірок та використовує -1 як eof (для різниці між 255 та -1). Я зазвичай використовую перекладачів інших народів, але цього разу мені потрібно бути плагіном і просувати свою власну:

jitbf --eof -1 -b 16 -c 200000000 random.bf < pg100.txt > pg100.txt.ran
jitbf --eof -1 -b 16 -c 200000000 random.bf < Glühwendel_brennt_durch.jpg > Glühwendel_brennt_durch.jpg.ran

jitfb компілює BrainFuck для оптимізованого C та зловживає perl Inline :: C для його запуску. Це пакети з моїм розширеним компілятором BrainFuck . З розміром і шириною комірки в аргументі вона виділить близько 400 МБ.


3

CJam, 22 байти

G,~q{5$H$+255%_@^o}/];

Для цього використовується генератор Фібоначчі з відсталим співвідношенням рецидивів s n = (s n-5 + s n-16 )% 255 (який я вибрав помилково, але він працює, тим не менш) і тривіальним насінням для генерації псевдовипадкового потоку байтів , який він потім XOR з входом.

Я перевірив свій код на CJam 0.6 , який був опублікований 1 травня 2014 року.

Як це працює

G,~                    e# Dump 0, 1, ... and 15 on the stack.
   q                   e# Read from STDIN.
    {             }/   e# For each character in the input.
     5$H$              e# Copy the sixth and 19th element from the stack.
         +255%         e# Push their sum modulo 255.
              _@       e# Duplicate and rotate the character on top.
                ^o     e# XOR and print.
                    ]; e# Clear the stack.

Оцінка

$ LANG=en_US
$ alias cjam='java -jar /usr/local/share/cjam/cjam-0.6.jar'
$ cjam thwart.cjam < pg100.txt > pg100.txt~
$ cjam thwart.cjam < pg100.txt~ > pg100.txt~~
$ diff -s pg100.txt pg100.txt~~
Files pg100.txt and pg100.txt~~ are identical
$ cjam thwart.cjam < Gluehwendel_brennt_durch.jpg > Gluehwendel_brennt_durch.jpg~
$ cjam thwart.cjam < Gluehwendel_brennt_durch.jpg~ > Gluehwendel_brennt_durch.jpg~~
$ diff -s Gluehwendel_brennt_durch.jpg Gluehwendel_brennt_durch.jpg~~
Files Gluehwendel_brennt_durch.jpg and Gluehwendel_brennt_durch.jpg~~ are identical
$ xz -kz5 pg100.txt~ Gluehwendel_brennt_durch.jpg~
$ wc -c thwart.cjam pg100.txt* Gluehwendel_brennt_durch.jpg*
      22 thwart.cjam
 5589889 pg100.txt
 5589889 pg100.txt~
 5589889 pg100.txt~~
 5590232 pg100.txt~.xz
 1659874 Gluehwendel_brennt_durch.jpg
 1659874 Gluehwendel_brennt_durch.jpg~
 1659874 Gluehwendel_brennt_durch.jpg~~
 1660016 Gluehwendel_brennt_durch.jpg~.xz
28999559 total

3

PHP, 117 + 0 + 0 + 0 + 0 = 117

Тому що ви б дійсно поклали на себе завдання керувати вашими даними непізнаваними будь-якою іншою мовою?

<?=substr(gmp_export(gmp_invert(2*gmp_import($s=stream_get_contents(STDIN))+1,$m=2*gmp_pow(256,strlen($s)))/2+$m),1);

Хоча всі інші рішення базуються на «захищених» конструкціях, таких як «генератори випадкових чисел» або «криптографія військового рівня», це просто інтерпретує рядки як відображення непарних чисел по модулю 2ulo256 ^ довжиною та обчислює їх модульну обернену .

Демонстрація:

$ php thwart.php < 100.txt.utf-8 > 100.txt.utf-8~
$ php thwart.php < 100.txt.utf-8~ > 100.txt.utf-8~~
$ diff -s 100.txt.utf-8 100.txt.utf-8~~
Files 100.txt.utf-8 and 100.txt.utf-8~~ are identical
$ php thwart.php < Glühwendel_brennt_durch.jpg > Glühwendel_brennt_durch.jpg~
$ php thwart.php < Glühwendel_brennt_durch.jpg~ > 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 100.txt.utf-8~ Glühwendel_brennt_durch.jpg~
$ wc -c *
 5589889 100.txt.utf-8
 5589889 100.txt.utf-8~
 5590232 100.txt.utf-8~.xz
 5589889 100.txt.utf-8~~
 1659874 Glühwendel_brennt_durch.jpg
 1659874 Glühwendel_brennt_durch.jpg~
 1660016 Glühwendel_brennt_durch.jpg~.xz
 1659874 Glühwendel_brennt_durch.jpg~~
     117 thwart.php
28999654 total

2

скрипт оболонки, 203

id|gpg --batch --passphrase-fd 0 --personal-compress-preferences Uncompressed $1 $2

Запуск:

% sh break.sh -c pg100.txt                       
% sh break.sh -d pg100.txt.gpg > pg100.txt-original
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected
% diff -s pg100.txt pg100.txt-original
Files pg100.txt and pg100.txt-original are identical
% sh break.sh -c Glühwendel_brennt_durch.jpg
% sh break.sh -d Glühwendel_brennt_durch.jpg.gpg > Glühwendel_brennt_durch.jpg-original
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected
% diff -s Glühwendel_brennt_durch.jpg Glühwendel_brennt_durch.jpg-original
Files Glühwendel_brennt_durch.jpg and Glühwendel_brennt_durch.jpg-original are identical
% xz -kz5 Glühwendel_brennt_durch.jpg.gpg 
% xz -kz5 pg100.txt.gpg 
% ls -ln
total 28340
-rw-r--r-- 1 1000 1000      84 May 24 04:33 break.sh
-rw-r--r-- 1 1000 1000 1659874 Jan 19 17:22 Glühwendel_brennt_durch.jpg
-rw-r--r-- 1 1000 1000 1659943 May 24 04:46 Glühwendel_brennt_durch.jpg.gpg
-rw-r--r-- 1 1000 1000 1660084 May 24 04:46 Glühwendel_brennt_durch.jpg.gpg.xz
-rw-r--r-- 1 1000 1000 1659874 May 24 04:46 Glühwendel_brennt_durch.jpg-original
-rw-r--r-- 1 1000 1000 5589891 May 24 03:55 pg100.txt
-rw-r--r-- 1 1000 1000 5589941 May 24 04:43 pg100.txt.gpg
-rw-r--r-- 1 1000 1000 5590284 May 24 04:43 pg100.txt.gpg.xz
-rw-r--r-- 1 1000 1000 5589891 May 24 04:43 pg100.txt-original

Не дуже портативний, але його можна зробити ціною пару байтів. Потрібен PGP (також можлива реалізація з OpenSSL). Різниця ~ 50 байт між закодованим файлом та оригіналом, ймовірно, може бути збережена.

Оцінка:

84 + abs (1659874 - 1659943) + max (1659874 - 1660084, 0) + abs (5589891 - 5589941) + max (5589891 - 5590284, 0) = 203


1

Пітон, оцінка = 183 + 7 + 6 + 0 + 0 = 196

Оцінка балів карає вас тим, що зробите файл повністю нестислимим, оскільки тоді стислий файл більший від накладних витрат на стиснення. Таким чином, моя програма робить їх трохи менше, ніж абсолютно нестислимими:

import sys
from random import randint as J,seed
x=sys.stdin.read()
seed(ord(x[1]))
n=int(2362*J(1,2)**2.359)
sys.stdout.write(x[:n]+''.join(chr(ord(c)^J(0,255))for c in x[n:]))

Результат:

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ cat photo.jpg | python break.py > photo.jpg~; cat photo.jpg~ | python break.py > photo.jpg~~; diff photo.jpg photo.jpg~~; xz -kz5 photo.jpg~

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ cat pg100.txt | python break.py > pg100.txt~; cat pg100.txt~ | python break.py > pg100.txt~~; diff pg100.txt pg100.txt~~; xz -kz5 pg100.txt~

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ ls -l
total 28337
----------+ 1 Laxori mkpasswd     183 2014-05-24 13:43 break.py
----------+ 1 Laxori mkpasswd 5589891 2014-05-23 19:19 pg100.txt
-rw-r--r--+ 1 Laxori mkpasswd 5589891 2014-05-24 13:45 pg100.txt~
-rw-r--r--+ 1 Laxori mkpasswd 5589884 2014-05-24 13:45 pg100.txt~.xz
-rw-r--r--+ 1 Laxori mkpasswd 5589891 2014-05-24 13:45 pg100.txt~~
----------+ 1 Laxori mkpasswd 1659874 2014-05-23 19:19 photo.jpg
-rw-r--r--+ 1 Laxori mkpasswd 1659874 2014-05-24 13:44 photo.jpg~
-rw-r--r--+ 1 Laxori mkpasswd 1659880 2014-05-24 13:44 photo.jpg~.xz
-rw-r--r--+ 1 Laxori mkpasswd 1659874 2014-05-24 13:44 photo.jpg~~

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ python
Python 2.5.2 (r252:60911, Dec  2 2008, 09:26:14)
[GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 183 + abs(5589891-5589884) + abs(1659874-1659880)
196

При чинних правилах збір файлу не збільшується. Чи змінилися правила? Якщо так, то такі зміни були несправедливими щодо цієї програми.
kernigh

@kernigh: Так, вони змінилися після того, як я опублікував це. Воістину вони повинні були бути такими, якими вони є від самого початку.
Клавдіу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.