Cel
Utwórz program lub parę programów, które wspólnie zakłócają i naprawiają pliki w celu uniemożliwienia efektywnego działania LZMA2. Procedury zakłócania i naprawy muszą być wzajemne, aby można było dokładnie odzyskać oryginalny plik.
Cele
- Zebrane dzieła Szekspira w zwykłym UTF-8 (55889891 bajtów)
- Wikimedia Commons 2013 Zdjęcie roku w pełnej rozdzielczości (1 659 847 bajtów)
Metody kompresji
- Ubuntu / powiązane:
xz -kz5 <infile>
- Windows:
7z.exe a -txz -mx5 <outfile> <infile>
- Inne: Użyj kompresora LZMA2 o poziomie kompresji 5, który kompresuje dzieła Szekspira do 1570550 bajtów ± 100 bajtów.
Punktacja; suma (wszystko jest w bajtach ls -l
lub dir
to):
- Rozmiar (-y) programu (cokolwiek zbiorowo wymaga, aby odwracalnie „złamać” / naprawić plik)
- Różnica wielkości (absolutna) między:
- Surowe zebrane dzieła Szekspira i zmodyfikowana (nieskompresowana) kopia.
- Nieprzetworzone zdjęcie i zmodyfikowana (nieskompresowana) kopia.
- Różnica wielkości lub 0, w zależności od tego, która wartość jest większa między:
- Surowe zebrane dzieła Szekspira pomniejszone o zmodyfikowaną, skompresowaną kopię LZMA2.
- Nieprzetworzone zdjęcie bez zmodyfikowanej, skompresowanej kopii LZMA2.
Przykład
Słabo punktowany, leniwie golfowy, ale zgodny z Python 2.x przykład:
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)
Bieganie...
$ 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
Wynik
- = 194 + abs (5589891 - 5589891) + max (5589891 - 3014136, 0) + abs (1659874 - 1659874) + max (1659874 - 1646556, 0)
- = 194 + 0 + 2575755 + 0 + 13318
- 2 589 267 bajtów. Źle, ale brak działania na plikach daje wynik 4635153 bajtów.
Wyjaśnienie
To jest golf, więc starasz się zminimalizować swój wynik. Nie jestem pewien, czy komentarze wskazują na uzasadnioną lukę w mojej punktacji, czy też dlatego, że uczyniłem to zbyt skomplikowanym. W każdym razie chcesz NAJMNIEJSZY :
- kod źródłowy
- różnica między nieskompresowanym zmodyfikowanym plikiem a plikiem oryginalnym (np. jeśli zmodyfikujesz go przez dodanie bilionów zer na końcu, twój wynik wzrósł o bilion bajtów)
- różnica między skompresowanym zmodyfikowanym plikiem a plikiem oryginalnym (np. im bardziej pliki są nieściśliwe, tym wyższy wynik). Idealnie nieściśliwy plik, który rośnie nieznacznie lub wcale nie ma wartości 0.
code-challenge
compression
Nick T.
źródło
źródło
Odpowiedzi:
Python, wynik = 120
Tworzy jednorazową podkładkę przy użyciu md5 w trybie licznika . xors plik z nim. Ma to tę zaletę, że oryginalne i uszkodzone pliki mają ten sam rozmiar oraz że program przerywający i naprawiający to ten sam program.
Skompresowane, uszkodzone pliki są większe niż oryginały.
źródło
C, 51 = 51 + 0 + 0 + 0 + 0
Pod sztuczkami golfa program ten zapętla każdy bajt na standardowym wejściu i robi wyłączność - lub z nieskończonym padem od rand (). Przetestowałem to za pomocą rand () w libc OpenBSD 5.5.
Stosowanie:
Aby przetestować mój program, napisałem skrypt powłoki test.sh (57 linii) w celu skompilowania programu i obliczenia wyniku.
Uwagi na temat rand () i prawej zmiany
Każdy algorytm kompresji nie może kompresować losowych danych. Mogę ukryć pg100.txt i filament.jpg jako dane losowe, jeśli zaszyfruję je za pomocą szyfru strumieniowego .
Moim pierwszym pomysłem było wyłącznym-lub zwykłego tekstu z podkładką do wprowadzania tekstu zaszyfrowanego , a następnie przechowywać zarówno szyfrogram i pad w kodowanym pliku. Zwiększy to rozmiar pliku i zwiększy mój wynik. Oczywistym wyborem jest użycie tego samego padu dla każdego pliku i zapisanie tylko tekstu zaszyfrowanego w zaszyfrowanym pliku. Jeśli po prostu wywołam rand (), użyje domyślnego zera 1 i utworzy ten sam pad każdym razem .
OpenBSD 5.5 definiuje rand () w stdlib.h i rand.c :
Jest to liniowy generator kongruencjalny . Wielką wadą jest to, że niskie bity mają krótkie okresy. Pierwszy bit ma okres 2: jeśli rzucisz monetą
rand()&1
, trafi on w głowy, ogony, głowy, ogony i tak dalej. N-ty bit ma okres 2 n . Jest 31 bitów, więc cała sekwencja ma okres 2 31 .LZMA2 może znaleźć wzorce w krótkim okresie i je skompresować. Najkrótszy kod
~c^rand()
zajmuje niskie 8 bitów i nie zapobiega kompresji. Właściwa zmiana~c^rand()>>9
pomaga, ale niewystarczająco. Używam~c^rand()>>23
.~c
WYNIK: 4227957 = 40 + 0 + 0 + 4019391 + 208526~c^rand()
WYNIK: 2474616 = 47 + 0 + 0 + 2463735 + 10834~c^rand()>>9
WYNIK: 350717 = 50 + 0 + 0 + 350667 + 0~c^rand()>>23
WYNIK: 51 = 51 + 0 + 0 + 0 + 0źródło
BrainFuck : 129 (129 + 0 + 0 + 0 + 0) *
random.bf (dodano kanały dla zwiększenia czytelności)
Aby stworzyć
unrandom.bf
, musisz zmienić ostatni + w drugiej linii.Większość kodu oparta jest na generatorze liczb losowych Daniela B Cristofaniego według Reguły 30 dostosowanym do dodawania liczby do każdego wejścia i kończenia, gdy nie ma już żadnych danych wejściowych.
* Przetestowałem dotychczas przetworzone bajty 212992 (przetworzone po 12 godzinach) i oba pliki zmieniają się w skompresowany plik 213064. Myślę, że można to zrobić do końca tygodnia na pewno, ale nie chcę czekać z wysłaniem. Zaktualizuję wynik, jeśli jest niepoprawny, ale zachowaj rozwiązanie, ponieważ przepis 30 rządzi!
Ciekawostki: Reguła 30 została odkryta przez Stephena Wolframa w 1983 roku i według Wikipedii jest używana do tworzenia losowych liczb całkowitych w Mathematica.
Kompilacja i uruchomienie:
Wykorzystuje wykładniczy czas i przestrzeń (iteruje ponad 32 więcej komórek na przetworzony znak), więc wymaga środowiska wykonawczego BrainFuck, który ma co najmniej 178 876 517 komórek do kodowania pliku Shakespear, nie traktuj non ascii jako Unicode, ma szersze niż 8 bitów komórki i wykorzystuje -1 jako eof (różni się między 255 a -1). Zwykle używam tłumaczy innych ludzi, ale tym razem muszę być wtyczką i promować własne:
jitfb kompiluje BrainFuck do zoptymalizowanego C i nadużywa Perla Inline :: C, aby go uruchomić. Jest dołączony do mojego kompilatora Extended BrainFuck . Przy rozmiarze i szerokości komórki w argumencie przydzieli około 400 MB.
źródło
CJam, 22 bajty
Używa opóźnionego generatora Fibonacciego z relacją powtarzalności s n = (s n-5 + s n-16 )% 255 (który wybrałem przez pomyłkę, ale mimo to działa) i trywialny materiał siewny do wygenerowania pseudolosowego strumienia bajtów , który następnie XORs z wejściem.
Przetestowałem swój kod w CJam 0.6 , który został opublikowany 1 maja 2014 r.
Jak to działa
Wynik
źródło
PHP, 117 + 0 + 0 + 0 + 0 = 117
Bo czy naprawdę powierzyłbyś zadanie zmanipulowania danych nie do poznania jakimkolwiek innym językiem?
Podczas gdy wszystkie inne rozwiązania są oparte na „bezpiecznych” konstrukcjach, takich jak „generatory liczb losowych” lub „kryptografia klasy wojskowej”, to jedno po prostu interpretuje ciągi znaków reprezentujące długości nieparzyste o długości modulo 2–256 ^ i oblicza ich modułową odwrotność .
Próbny:
źródło
skrypt powłoki, 203
Uruchamianie:
Niezbyt przenośny, ale może być wykonany kosztem kilku bajtów. Wymaga PGP (możliwa byłaby również implementacja z OpenSSL). Prawdopodobnie można zapisać różnicę około 50 bajtów między zakodowanym plikiem a oryginałem.
Punktacja:
84 + abs (1659874 - 1659943) + max (1659874 - 1660084, 0) + abs (5589891 - 5589941) + max (5589891 - 5590284, 0) = 203
źródło
Python, wynik = 183 + 7 + 6 + 0 + 0 = 196
Punktacja karze Cię za uczynienie pliku całkowicie nieściśliwym, ponieważ wtedy skompresowany plik jest większy niż narzut kompresji. Tak więc mój program czyni je nieco mniej niż całkowicie nieściśliwymi:
Wynik:
źródło