Wyzwanie
Napisz program, który bezstratnie kompresuje i dekompresuje tekst ASCII. Powinien specjalizować się w pracy z palindromami, w tym palindromami bez rozróżniania wielkości liter i interpunkcji. Najlepsza kompresja z najmniejszym źródłem wygrywa.
Punktacja
total_bytes_saved / sqrt(program_size)
- Najwyższy wynik wygrywa
total_bytes_saved
jest liczbą bajtów mniejszych skompresowanych ciągów niż oryginałów, łącznie w poniższych przypadkach testowych. program_size
to rozmiar w bajtach kodu źródłowego programów kompresujących i dekompresujących. Kod dzielony między nimi musi być policzony tylko raz.
Na przykład, jeśli istnieje 10 przypadków testowych, a program 100-bajtowy zapisał 5 bajtów na 7 przypadków testowych, po 10 na 2 z nich, ale ostatni przypadek testowy był o 2 bajty dłuższy, rozwiązanie uzyskałoby wynik 5,3. ( (7 * 5 + 10 * 2 - 2) / sqrt(100) = 5.3
)
Przypadki testowe
tacocat
toohottohoot
todderasesareddot
amanaplanacanalpanama
wasitacaroracatisaw?
Bob
IManAmRegalAGermanAmI
DogeeseseeGod
A Santa at NASA
Go hang a salami! I'm a lasagna hog.
Zasady
- Obowiązują standardowe luki.
- Kompresja musi działać na wszystkich drukowanych ciągach tekstowych ASCII (bajty 32-126 włącznie), a nie tylko na palindromach. Jednak tak naprawdę nie musi oszczędzać miejsca na żadne dane wejściowe.
- Wyjściem może być dowolna sekwencja bajtów lub znaków, niezależnie od ich implementacji lub wewnętrznej reprezentacji (ciągi, listy i tablice są na przykład fair game). Jeśli kodujesz do UTF-8, licz bajty, a nie znaki. Szerokie ciągi znaków (np. UTF-16 lub UTF-32) są niedozwolone, chyba że jedynymi możliwymi zastosowanymi punktami kodowymi są między 0 a 255.
- Wbudowane kompresje / dekompresje są niedozwolone.
Ze względu na naszą przyjemność publikuj skompresowane ciągi wraz z kodem źródłowym.
AKTUALIZACJA 1: Punktacja została zmieniona z total_bytes_saved / program_size
na total_bytes_saved / sqrt(program_size)
, aby zwiększyć wagę do lepszej kompresji, a mniej do agresywnego golfa. Dostosuj odpowiednio swoje wyniki.
AKTUALIZACJA 2: ustalona wasitacaroraratisaw?
nawasitacaroracatisaw?
źródło
wasitacaroraratisaw?
to kontrprzykład[32-126]
jest1000 *
część była naprawdę potrzebna, i nie, nie sądzę, że sprawi, że wynik będzie bardziej „satysfakcjonujący”;)Odpowiedzi:
JavaScript (ES6), 3.143 (81 bajtów zapisanych, program 664 bajtów)
Teraz, gdy jestem dość zadowolony z tego programu (i systemu oceniania), napiszę trochę wyjaśnienia.
Podstawową ideą jest skompresowanie danych wejściowych w ciąg bitów, a następnie skompresowanie każdego zestawu 8 bitów w bajt. Dla celów wyjaśnienia po prostu manipuluję ciągiem bitów.
Ciąg bitów można podzielić na kilka sekcji:
Nagłówek jest bardzo prostym odwzorowaniem:
Dane listowe są również dość proste. Po pierwsze, wszystkie nie-litery są wydobywane z ciągu, a wszystkie litery są konwertowane na wielkie litery. Jeśli powstały ciąg jest palindromem, odwrócona połowa jest usuwana. Następnie stosuje się to mapowanie:
Ta sekcja jest zakończona
111
. Potem przychodzą dane dotyczące stylizacji, w których przechowywane są duże / małe litery i nie-litery. Działa to tak:Przechodząc przez powyższy przykład, mamy
Po osiągnięciu końca ciągu bitowego wszystkie pozostałe znaki z danych literowych są dołączane do wyniku. To oszczędza nam konieczności wykonywania ostatniego
000...001
i pozwala nam skrócić te bity z łańcucha.Przeglądając przypadki testowe:
źródło
Bob
.Bob
naprawdę po prostu trafił na miejsce - 1 bit dla nagłówka, 10 + 3 bity dla dwóch liter i 2 bity dla pojedynczej dużej litery. Nie mogłem tego skrócić, gdybym się starał ...-0+9
+9
będzie łączyć się z łańcuchem, podczas gdy-~8
robi+9
arytmetycznie (ponieważ-
nic nie robi dla łańcuchów, więc interpretuje to jako liczbę). W takim przypadku-~8
jest całkiem sprytny. :) Ładna odpowiedź btw, +1 ode mnie! Bardzo inteligentne przechowywanie wszystkich informacji w takich bitach, nawet oszczędzając bajtBob
.Python 2: 2.765 (zapisano 70 bajtów, program 641 bajtów)
Trochę zmieniłem swoje podejście. Teraz działa dobrze na niedoskonałych palindromach. Nie ma skompresowanych ciągów, które będą dłuższe niż wejście. Idealne palindromy o równej długości zawsze będą kompresować do 50% oryginalnego rozmiaru.
Wyniki
Jako bonus oszczędza 6 bajtów mojego niewłaściwego palindromu, który miałem wcześniej.
Wyjaśnienie
Dekompresja używa stosu. Punkty kodowe od 32-127 są traktowane dosłownie. Jeśli znak jest literą, wartość jest również wypychana na stos. Wartości 128–192 są używane dla liter z odwróconą wielkością liter, więc litera z odwróconą wielkością liter (
o^32
ze względu ASCII) jest wypychana na stos, a normalna litera jest dodawana do łańcucha. Wartości 192-255 są używane do dodawania liter bez pchania na stos, więc jest to stosowane, gdy litery nie pasują, a dla środkowej litery w palindromach o nieparzystej długości. Punkty kodowe 1-15 wskazują, że stos powinien zostać wyskakujący tyle razy. Punkty kodowe 17–31 są podobne, ale drukują najpierw spację, zanim wyskoczą ze stosu. Na końcu wejścia znajduje się również domyślna instrukcja „pop aż pusta”.Kompresor działa z obu końców i składa się w pasujące litery o wartościach 1-31. Pomija znaki inne niż litery. Gdy litery się zgadzają, ale nie ma to miejsca, dodaje 64 do lewej litery i zwiększa prawą literę. Pozwala to zaoszczędzić miejsce
IManAmRegalAGermanAmI
. Na środku lub gdy litery się nie zgadzają, to po obu stronach 128. Nie mogę tam dodać, ponieważ muszę unikać specjalnego przypadku, w którymleft == right
. Składając sąsiednie znaczniki pop po prawej stronie, muszę sprawdzić, czy sąsiedni nie przepełni się w punkcie kodowym 16, ponieważ potrzebuję tego dla spacji. (W rzeczywistości nie stanowi to problemu dla żadnego z ciągów przypadków testowych)EDYCJA 1 : Nigdy więcej wersji bez golfa.
źródło
Python3, 1.833 (zapisane 25 bajtów, program 186 bajtów)
Po prostu proste kodowanie entropijne równego prawdopodobieństwa 0 rzędu. Brak optymalizacji specyficznych dla palindromu.
źródło
Java 8, wynik: 1,355 (20 bajtów zapisanych / 218 (107 + 111) bajtów)
Funkcja kompresji (zawiera trzy niedrukowalne znaki ASCII):
Funkcja dekompresji (zawiera dwa niedrukowalne znaki ASCII):
Wyjaśnienie:
Wypróbuj online.
Kompresuje tylko idealne palindromy.
źródło