Twoim zadaniem dzisiaj jest wynalezienie kompresora tekstu.
Zadanie
Napisz dwie funkcje:
Paker jest funkcją, która przyjmuje ciąg znaków ASCII (U, U + 0000 + 007F) i wysyła unikodowego (U + 0000 U + 10FFFF) zawierający najmniejszą liczbę znaków możliwe.
Unpacker to funkcja, która akceptuje zakodowany ciąg Unicode i wyprowadza dokładnie oryginalny ciąg ASCII.
Wkład
Jedynym autoryzowanym wejściem jest ciąg ASCII (dla pakującego) i spakowany ciąg Unicode (dla rozpakowacza). Bez wkładu użytkownika, bez połączenia z Internetem, bez użycia systemu plików.
Twoje funkcje mogą mieć dostęp do tej listy angielskich słów . Możesz użyć tej listy jako lokalnego pliku txt lub skopiować jej zawartość do kodu źródłowego jako ciąg lub tablicę ciągów .
W swoich funkcjach nie można zakodować na stałe poniższych fragmentów.
Wydajność
Jedynym autoryzowanym wyjściem dla obu funkcji jest ciąg.
Dane wyjściowe rozpakowywacza muszą zawierać dokładnie takie same znaki, jak dane wejściowe pakowacza.
Twoje dane wejściowe i wyjściowe mogą korzystać z dowolnego kodowania znaków obsługującego wszystkie znaki Unicode (UTF-8/16/32, GB18030, ...), ponieważ wynik będzie zależał tylko od liczby znaków Unicode na wyjściu. Proszę jednak dokładnie określić, jakiego kodowania używasz.
Aby policzyć liczbę znaków Unicode w danych wyjściowych, możesz użyć tego narzędzia: http://mothereff.in/byte-counter
Punktacja
Wpis musi umożliwiać pakowanie i rozpakowywanie 10 następujących fragmentów tekstu (które wziąłem na tym forum).
Twój wynik będzie sumą rozmiarów 10 spakowanych ciągów znaków (w znakach Unicode) + rozmiaru twoich dwóch funkcji (również w znakach Unicode)
Nie licz rozmiaru słownika, jeśli go używasz.
Podaj we wpisach „wynik” każdego fragmentu i jego zapakowanej wersji.
Najniższy wynik wygrywa.
Dane
Oto fragmenty do zakodowania w celu obliczenia wyniku:
Tekst piosenki 1: Rick Roll (1870b): Nie jesteśmy obcy w kodowaniu golfa, znasz zasady i ja też
Nie jesteśmy obcymi ludźmi do kochania Znasz zasady i ja też Myślę o pełnym zaangażowaniu Nie dostałbyś tego od żadnego innego faceta Chcę ci tylko powiedzieć, jak się czuję Muszę cię zrozumieć Nigdy się nie poddawaj Nigdy cię nie zawiodę Nigdy nie będę biegał i cię opuszczał Nigdy nie sprawię, że będziesz płakać Nigdy się nie pożegnam Nigdy nie kłamię i nie skrzywdzę cię Znamy się od tak dawna Twoje serce boli, ale Jesteś zbyt nieśmiały, żeby to powiedzieć Wewnątrz oboje wiemy, co się dzieje Znamy tę grę i zagramy w nią A jeśli zapytasz mnie, jak się czuję Nie mów mi, że jesteś zbyt ślepy, żeby to zobaczyć Nigdy się nie poddawaj Nigdy cię nie zawiodę Nigdy nie będę biegał i cię opuszczał Nigdy nie sprawię, że będziesz płakać Nigdy się nie pożegnam Nigdy nie kłamię i nie skrzywdzę cię Nigdy się nie poddawaj Nigdy cię nie zawiodę Nigdy nie będę biegał i cię opuszczał Nigdy nie sprawię, że będziesz płakać Nigdy się nie pożegnam Nigdy nie kłamię i nie skrzywdzę cię (Ooh, poddaj się) (Ooh, poddaj się) (Ooh) Nigdy nie dam, nigdy nie dam (Poddaj się) (Ooh) Nigdy nie dam, nigdy nie dam (Poddaj się) Znamy się od tak dawna Twoje serce boli, ale Jesteś zbyt nieśmiały, żeby to powiedzieć Wewnątrz oboje wiemy, co się dzieje Znamy tę grę i zagramy w nią Chcę ci tylko powiedzieć, jak się czuję Muszę cię zrozumieć Nigdy się nie poddawaj Nigdy cię nie zawiodę Nigdy nie będę biegał i cię opuszczał Nigdy nie sprawię, że będziesz płakać Nigdy się nie pożegnam Nigdy nie kłamię i nie skrzywdzę cię Nigdy się nie poddawaj Nigdy cię nie zawiodę Nigdy nie będę biegał i cię opuszczał Nigdy nie sprawię, że będziesz płakać Nigdy się nie pożegnam Nigdy nie kłamię i nie skrzywdzę cię Nigdy się nie poddawaj Nigdy cię nie zawiodę Nigdy nie będę biegał i cię opuszczał Nigdy nie sprawię, że będziesz płakać Nigdy się nie pożegnam Nigdy nie kłamię i nie skrzywdzę cię
2: The Golfer (412b): Gra w golfa ASCII-art
„\. . |> 18 >> \. „. | O >>. „o | \. | / \. | / /. ” | jgs ↑ ^^^^^^^^^^
3: liczba diamentów (233b): wydrukuj ten diament
1 121 12321 1234321 123454321 12345654321 1234567654321 123456787654321 12345678987654321 123456787654321 1234567654321 12345654321 123454321 1234321 12321 121 1
4: alfabet cztery razy (107b): Wydrukuj alfabet cztery razy
ABCDEFGHIJKLMNOPQRSTU VWXYZ qwertyuiopasdfghjklzxcvbnm pyfgcrlaoeuidhtnsqjkxbmwvz zyxwvutsrqponmlkjihgfedcba
5: Tekst Old McDonald's (203b): Funkcja Old MacDonald
Stary MacDonald miał farmę, EIEIO, A na tej farmie miał krowę, EIEIO, Z muczeniem tutaj i muczeniem tutaj, Tutaj muczenie, muczenie, wszędzie muczenie muczenie, Stary MacDonald miał farmę, EIEIO!
6: Rock around the clock lyrics (144b): Rock Around the Clock
1, 2, 3 godzina, 4 godzina rock, 5, 6, 7 godzina, 8 godzina rock, 9, 10, 11 godzina, 12 godzina rock, Będziemy dziś kołysać się przez całą dobę.
7: Hello World (296b): Powiedz światu „Hello” w sztuce ASCII
_ _ _ _ _ _ _ _ | | | | ___ | | | ___ __ _____ _ __ | | __ | | | | | _ | | / _ \ | | / _ \ \ \ / \ / / _ \ | „__ | | / _` | | | _ | __ / | | (_) | \ VV / (_) | | | | (_ | | _ | | _ | | _ | \ ___ | _ | _ | \ ___ () \ _ / \ _ / \ ___ / | _ | | _ | \ __, _ (_) | /
8: Irlandzkie błogosławieństwo (210b): Stare irlandzkie błogosławieństwo
Niech droga wzniesie się, by cię poznać Niech wiatr będzie zawsze na twoich plecach Niech słońce świeci ciepło na twoją twarz Deszcze padają na twoje pola I dopóki się nie spotkamy Niech Bóg trzyma cię w zagłębieniu swojej ręki
9: Tekst piosenki old lady (1208b): There Was an Old Lady
Była starsza pani, która połknęła muchę. Nie wiem, dlaczego połknęła tę muchę, Może umrze. Była starsza pani, która połknęła pająka, Kręciło się to w niej i igrało. Połknęła pająka, aby złapać muchę, Nie wiem, dlaczego połknęła tę muchę, Może umrze. Była starsza dama, która połknęła ptaka, Jak absurdalne jest połykanie ptaka. Połknęła ptaka, aby złapać pająka, Połknęła pająka, aby złapać muchę, Nie wiem, dlaczego połknęła tę muchę, Może umrze. Była starsza pani, która połknęła kota, Wyobraź sobie, że połkniesz kota. Połknęła kota, aby złapać ptaka, Połknęła ptaka, aby złapać pająka, Połknęła pająka, aby złapać muchę, Nie wiem, dlaczego połknęła tę muchę, Może umrze. Była starsza pani, która połknęła psa, Co za świnia do połknięcia psa. Połknęła psa, aby złapać kota, Połknęła kota, aby złapać ptaka, Połknęła ptaka, aby złapać pająka, Połknęła pająka, aby złapać muchę, Nie wiem, dlaczego połknęła tę muchę, Może umrze. Była starsza pani, która połknęła konia, Oczywiście umarła.
10: adres gettysburg (1452b): Jak losowy jest adres Gettysburg
Cztery dziesiątki i siedem lat temu nasi ojcowie zrodzili na tym kontynencie nowy naród, poczęty w wolności i poświęcony twierdzeniu, że wszyscy ludzie są równi. Teraz jesteśmy zaangażowani w wielką wojnę domową, sprawdzając, czy ten naród lub jakikolwiek naród tak pomyślany i oddany może przetrwać długo. Spotkaliśmy się na wielkim polu bitwy tej wojny. Przybyliśmy, aby poświęcić część tego pola, jako ostateczne miejsce spoczynku dla tych, którzy tutaj oddali życie, aby ten naród mógł żyć. Zasadniczo i słusznie powinniśmy to zrobić. Ale w szerszym znaczeniu nie możemy poświęcić, nie możemy poświęcić, nie możemy poświęcić tej ziemi. Odważni ludzie, żywi i martwi, którzy tu walczyli, poświęcili ją, znacznie ponad naszą słabą moc dodawania lub niszczenia. Świat niewiele zauważy, ani długo nie zapamięta tego, co tu mówimy, ale nigdy nie zapomni, co tutaj zrobili. To my, żywi, powinniśmy poświęcić się tutaj niedokończonemu dziełu, które walczyli tutaj tak szlachetnie. Raczej jesteśmy tutaj, aby poświęcić się wielkiemu zadaniu, które przed nami stoi - że od tych czcigodnych umarłych poświęcamy się temu celowi, dla którego oddali ostatnią miarę oddania - że tutaj bardzo postanawiamy, że ci umarli nie będą umarli na próżno - aby naród ten, pod Bogiem, narodził się na nowo w wolności - i aby lud rządził ludem, bo lud nie zginie z ziemi.
Łącznie (nieskompresowane): 6135 znaków / bajtów.
Baw się dobrze!
private static final String RICK_ROLL_RETURN = "We're no strangers to love...
Odpowiedzi:
Haskell - 5322 punkty
Bajty kodu:
686
Oryginalny rozmiar :
6147
= 1871+415+234+108+204+145+297+211+1209+1453
Zakodowany rozmiar:
4636
= 1396+233+163+92+153+115+197+164+979+1144
Ocena:
686+ 4636
Kompresja liczby znaków:
~25%
Kod
Pomijając optymalizacje, przechowuje wartości pomiędzy
0
i7f
w znakach Unicode jako ich główne czynniki.Nie obniża liczby bajtów zakodowanego wyjścia, tylko obniża liczbę znaków Unicode. Na przykład, test nr 4 zawiera
108
znaki i wyjście kodowane92
. Ich rozmiary są jednak odpowiednie108
i364
bajtów.Jak to działa
Kodowanie
n
.n
następnie przeprowadza się wykaz jego głównych czynnikówps
.1
. Oznacza to, że one, czynniki, mogą być przechowywane jako indeksy na zaledwie 5 bitach.1
jest szczególnym przypadkiem i jest reprezentowany przez pustą listę.ps
kodowaniu można teraz rozpocząć.ps
jest konwertowana na swój indeks na liście 32 unikalnych czynników (w powyższym kodzie ta lista jest oznaczona jakoa
).ps
należy spłaszczyć. Aby zachować integralność danych, każda lista jest konwertowana na inną listę dwóch częścifs
.fs
można następnie upakować w znaki Unicode przy użyciu przesunięcia bitowego.Rozszyfrowanie
1
pasuje, chciałbym ci to przypomniećproduct [] == 1
.Testy
Używanie tego interfejsu do testowania byłoby bolesne, więc skorzystałem z tej funkcji, aby przedstawić poniższe wyniki.
Próba
Wyjście funkcji kodowania
g
dla testu nr 4 jest takie"\99429\582753\135266\70785\35953\855074\247652\1082563\68738\49724\164898\68157\99429\67973\1082404\587873\73795\298017\330818\198705\69861\1082435\595009\607426\36414\69873\855074\265249\346275\67779\68738\77985\1082513\821353\132131\101410\247652\1082562\49724\164898\67649\594977\34915\67746\50273\135265\103997\563265\103457\1086021\99399\584802\70753\73889\34882\582722\411459\67779\68740\1084516\1082563\1091681\103491\313282\49724\164897\68705\135741\69858\50241\607426\35905\608421\1082435\69858\50274\71777\43075\298018\280517\1082404\67971\36017\955425\67665\919600\100452\132129\214883\35057\856097\101474\70753\135737"
lub jeśli jesteś biegły w bełkocie, to
𘑥𡁢𑒁豱𐲂숼𨐢𘑥𐦅𒁃𰠱𑃥踾𑃱𐲂𓂡𠐣𘰢숼𨐢𐡁衣쑡𡁡𘑇𑑡𒂡衂𐲄숼𨐡𡈽𑃢쑁豁𑃢쑢ꡃ𐦃貱𐡑𘡤𠐡裱𘱢𑑡𡈹
Dodatkowe uwagi
edTest
rozmiar testów są spójne, ale nadal różnią się od wskazanego rozmiaru w pytaniu.—
), że zastąpione-
, ponieważ są one na zewnątrz0
-7f
zakres.00
przypadek podstawowy,01
powtórz wszystko,10
powtórz oprócz ostatniego,11
powtórz oprócz dwóch ostatnich.źródło
abcdefghijklm...
na.𘑥𡁢𑒁豱...
Czy mógłbyś wyjaśnić to trochę bardziej, proszę? Ponadto poprawiłem zliczanie znaków i zamieniłem myślniki na # 10 w pytaniu. Jednak moje liczby są nadal inne niż twoje. Nie wiem, dlaczego użyłem narzędzia mothereff.in.C ++ (C ++ 11), 2741 punktów
Ta odpowiedź używa UTF-32 jako kodowania skompresowanego tekstu.
Char liczy się i zdobywa punkty
Kod: 593 znaków (znak nowej linii jest usuwany)
Skompresowane teksty (znaki Unicode) : 654 + 145 + 82 + 38 + 51 + 104 + 73 + 423 + 506 = 2148 (liczone
wc -m
jako liczba znaków Unicode zamiast bajtów, liczba bajtów jest, tak jak w przypadku odpowiedzi @ gxtaillon , wyższa niż oryginały, łącznie 8413 bajtów, zgodnie z policzeniemwc -c
).Współczynnik kompresji (ASCII do Unicode) : 35,01% (przy użyciu 6135 bajtów z pytania (tak samo jak
wc -c
))Strzec się:
Wiele powłok nie jest w stanie obsłużyć znaków Unicode generowanych przez ten program. Zatem dekompresja może prowadzić do obcięcia tekstu gdzieś, gdy powłoka nie może obsłużyć znaku, ponieważ dane wejściowe są pobierane przez
stdin
z powłoki.Kompilacja
Powinien się skompilować z
clang++
ig++ -std=c++11
, ale to pokaże jakieś ostrzeżenia o pierwszeństwa operatora, jako wyraz jakb<<20-n&0xFFFFF
nie będą traktowane jak((b << 20) - n) & 0xFFFFF
, jak można by się spodziewać, ale raczej jako(b << (20 - n)) & 0xFFFFF
.Stosowanie
./compress
../compress c
celu kompresji lub./compress d
dekompresji. (Ostrożnie, pominięcie opcji daje SEGFAULT (sprawdzanie błędów jest tak drogie, że znak jest drogi ...), a inne opcje (takie jak używanieD
zamiastd
) mogą dawać nieoczekiwane wynikistdin
a dane wyjściowe zapisywanestdout
Jak to działa
Nie golfił
Wyjaśnienie
Ponieważ wszystkie znaki Unicode od
U+0000
doU+10FFFF
są dozwolone, możemy użyć 20 bitów na znak Unicode:U+FFFFF
używa 20 bitów i nadal znajduje się w dozwolonym zakresie. Dlatego staramy się po prostu wcisnąć wszystkie pojedyncze bity znaków ASCII w znaki Unicode, aby przechowywać wiele znaków ASCII w jednym znaku Unicode. Musimy jednak również przechowywać liczbę bitów użytych w ostatnim znaku Unicode, ponieważ nieużywane bity śmieci mogą być inaczej interpretowane jako właściwe skompresowane znaki ASCII. Ponieważ maksymalna liczba używanych bitów w ostatnim znaku Unicode wynosi 20, potrzebujemy do tego 5 bitów, które są umieszczone na początku skompresowanych danych.Przykładowe dane wyjściowe
To jest wynik na przykład # 4 (podany przez
less
):(
쏏𦛏
podaj<U+C3CF><U+266CF>
jako kody znaków, ale mogłem się pomylić)źródło
Python 3, 289 + 818 = 1107 punktów
Tylko lekko golfa.
Całkowity rozmiar kodu wynosi 289 bajtów i koduje podane 6135 bajtów na 818 znaków Unicode - całkowita liczba bajtów wyjściowych wynosi 3201 bajtów, znacznie mniej niż pierwotne dane wejściowe.
Koduje za pomocą zlib, a następnie za pomocą kodowania Unicode. Potrzebna była dodatkowa logika, aby uniknąć surogatów (których Python naprawdę nienawidzi).
Przykładowe dane wyjściowe z # 4, jak widać
less
(37 znaków Unicode):Program sterownika do testowania:
Liczniki bajtów wyjściowych:
źródło
p
jest pakującym,u
jest rozpakowującym.Python 2 - 1141 punktów
Rozmiar kodu to
281
bajty i koduje6135
bajty na860
znaki Unicode.Jak to działa:
Aby zakodować:
19
bitów, dodaj1
trochę na początku każdego z nich, a następnie przekonwertuj na znaki Unicode.Dekodowanie jest odwrotne.
Zauważ, że niektóre wersje Pythona mogą obsługiwać tylko znaki Unicode do
0xFFFF
, dlatego ten kod podniesie wartośćValueError
.źródło