Herausforderung
Schreiben Sie ein Programm, das ASCII-Text verlustfrei komprimiert und dekomprimiert. Es sollte darauf spezialisiert sein, gut mit Palindromen zu arbeiten, einschließlich Palindromen, bei denen die Groß- und Kleinschreibung und die Zeichensetzung keine Rolle spielen. Die beste Komprimierung mit der kleinsten Quelle gewinnt.
Wertung
total_bytes_saved / sqrt(program_size)
- Höchste Punktzahl gewinnt
total_bytes_saved
gibt an, wie viele Bytes die komprimierten Zeichenfolgen kleiner sind als die Originale, insgesamt in den folgenden Testfällen. program_size
ist die Größe des Quellcodes sowohl des Komprimierungs- als auch des Dekomprimierungsprogramms in Byte. Der zwischen den beiden geteilte Code muss nur einmal gezählt werden.
Wenn beispielsweise 10 Testfälle vorhanden sind und ein 100-Byte-Programm 5 Bytes in 7 Testfällen gespeichert hat, jeweils 10 in 2 davon, aber der letzte Testfall 2 Bytes länger war, würde die Lösung 5,3 Punkte erzielen. ( (7 * 5 + 10 * 2 - 2) / sqrt(100) = 5.3
)
Testfälle
tacocat
toohottohoot
todderasesareddot
amanaplanacanalpanama
wasitacaroracatisaw?
Bob
IManAmRegalAGermanAmI
DogeeseseeGod
A Santa at NASA
Go hang a salami! I'm a lasagna hog.
Regeln
- Es gelten Standardlücken.
- Die Komprimierung muss für alle druckbaren ASCII-Textzeichenfolgen (Bytes 32-126, einschließlich) und nicht nur für Palindrome funktionieren. Tatsächlich muss jedoch kein Platz für Eingaben gespart werden.
- Die Ausgabe kann eine beliebige Folge von Bytes oder Zeichen sein, unabhängig von ihrer Implementierung oder internen Darstellung (beispielsweise sind alle Zeichenfolgen, Listen und Arrays ein faires Spiel). Wenn Sie nach UTF-8 codieren, zählen Sie die Bytes, nicht die Zeichen. Breite Zeichenfolgen (z. B. UTF-16 oder UTF-32) sind nur zulässig, wenn die einzigen Codepunkte, die möglicherweise verwendet werden, zwischen 0 und 255 liegen.
- Integrierte Komprimierungs- / Dekomprimierungsfunktionen sind nicht zulässig.
Veröffentlichen Sie die komprimierten Zeichenfolgen zu unserem eigenen Vergnügen mit Ihrem Quellcode.
UPDATE 1: Die Wertung wurde von total_bytes_saved / program_size
auf total_bytes_saved / sqrt(program_size)
geändert, um einer besseren Kompression mehr Gewicht und einem aggressiven Golfen weniger Gewicht zu verleihen. Passen Sie Ihre Ergebnisse entsprechend an.
UPDATE 2: behoben wasitacaroraratisaw?
zu seinwasitacaroracatisaw?
quelle
wasitacaroraratisaw?
ist ein Gegenbeispiel dazu[32-126]
?1000 *
Teil wirklich gebraucht wird, und nein, ich glaube nicht, dass sich die Partitur dadurch "befriedigender" anfühlt;)Antworten:
JavaScript (ES6), 3.143 (81 Byte gespeichert, 664 Byte Programm)
Nachdem ich mit diesem Programm (und dem Bewertungssystem) ziemlich zufrieden bin, schreibe ich eine kurze Erklärung.
Die Grundidee besteht darin, die Eingabe in eine Folge von Bits zu komprimieren und dann jeden Satz von 8 Bits in ein Byte zu komprimieren. Zu Erklärungszwecken werde ich nur die Bitfolge manipulieren.
Die Bitfolge kann in mehrere Abschnitte unterteilt werden:
Der Header ist ein sehr einfaches Mapping:
Briefdaten sind auch ziemlich einfach. Zunächst werden alle Nichtbuchstaben aus der Zeichenfolge extrahiert und alle Buchstaben in Großbuchstaben umgewandelt. Wenn die resultierende Zeichenfolge ein Palindrom ist, wird die umgekehrte Hälfte entfernt. Dann wird dieses Mapping angewendet:
Dieser Abschnitt endet mit
111
. Danach folgen die Styling-Daten, in denen Groß- / Kleinschreibung und Nichtbuchstaben gespeichert sind. Das funktioniert so:Gehen wir also das oben gezeigte Beispiel durch
Wenn das Ende der Bitfolge erreicht ist, werden alle verbleibenden Zeichen aus den Buchstabendaten an das Ergebnis angehängt. Dies erspart uns das letzte Mal,
000...001
und wir können diese Bits von der Zeichenfolge abschneiden.Durchlaufen der Testfälle:
quelle
Bob
.Bob
wirklich gerade so ergeben - 1 Bit für den Header, 10 + 3 Bit für die beiden Buchstaben und 2 Bit für den einzelnen Großbuchstaben. Könnte es nicht kürzer werden, wenn ich mein-0+9
+9
würde sich auf die Zeichenkette konzentrieren, während-~8
dies+9
arithmetisch-
geschieht (da für Zeichenketten nichts unternommen wird, interpretiert es diese als Zahl). In diesem Fall-~8
ist es ziemlich schlau. :) Schöne Antwort übrigens, +1 von mir! Sehr intelligentes Speichern aller Informationen in solchen Bits, sogar das Speichern eines BytesBob
.Python 2: 2.765 (70 Byte gespeichert, 641 Byte Programm)
Ich habe meine Herangehensweise ein wenig geändert. Es funktioniert jetzt gut bei unvollkommenen Palindromen. Es gibt keine komprimierten Zeichenfolgen, die länger als die Eingabe sind. Perfekte Palindrome mit gerader Länge werden immer auf 50% der Originalgröße komprimiert.
Ergebnisse
Und als Bonus spart es 6 Bytes auf meinem falschen Palindrom, das ich vorher hatte.
Erläuterung
Dekomprimierung verwendet einen Stapel. Codepunkte von 32-127 werden wörtlich behandelt. Wenn ein Zeichen ein Buchstabe ist, wird auch ein Wert auf den Stapel geschrieben. Die Werte 128-192 werden für Groß- und Kleinschreibung verwendet, sodass der durch Groß- und Kleinschreibung gekippte Buchstabe (
o^32
aufgrund der Anordnung von ASCII) auf den Stapel verschoben und der normale Buchstabe zur Zeichenfolge hinzugefügt wird. Die Werte 192-255 werden verwendet, um Buchstaben hinzuzufügen, ohne sie auf den Stapel zu schieben. Dies wird also verwendet, wenn die Buchstaben nicht übereinstimmen, und für den mittleren Buchstaben in Palindromen ungerader Länge. Die Codepunkte 1-15 geben an, dass der Stapel so oft gepoppt werden soll. Die Codepunkte 17-31 sind ähnlich, drucken jedoch zuerst ein Leerzeichen, bevor sie vom Stapel springen. Es gibt auch eine implizite Anweisung "Pop bis leer" am Ende einer Eingabe.Der Kompressor arbeitet von beiden Seiten und faltet sich in übereinstimmenden Buchstaben als Werte 1-31. Es werden keine Buchstaben übersprungen. Wenn die Buchstaben übereinstimmen, die Groß- / Kleinschreibung jedoch nicht, wird dem linken Buchstaben 64 hinzugefügt und der rechte Buchstabe erhöht. Dies ermöglicht es, Platz zu sparen
IManAmRegalAGermanAmI
. In der Mitte oder wenn die Buchstaben nicht übereinstimmen, sind es 128 zu beiden Seiten. Ich kann dort nicht hinzufügen, weil ich den Sonderfall vermeiden muss, in demleft == right
. Wenn ich benachbarte Pop-Marker auf der rechten Seite falte, muss ich sicherstellen, dass der benachbarte nicht in Codepoint 16 überläuft, da ich den für Leerzeichen benötige. (Dies ist eigentlich kein Problem für eine der Testfall-Zeichenfolgen.)EDIT 1 : Keine ungolfed version mehr.
quelle
Python3, 1.833 (25 Byte gespeichert, 186 Byte Programm)
Nur einfache Entropiecodierung mit gleicher Wahrscheinlichkeit nullter Ordnung. Keine palindromspezifischen Optimierungen.
quelle
Java 8, Score: 1.355 (20 Bytes gespeichert / 218 (107 + 111) Bytes)
Komprimierungsfunktion (enthält drei nicht druckbare ASCII-Zeichen):
Dekomprimierungsfunktion (enthält zwei nicht druckbare ASCII-Zeichen):
Erläuterung:
Probieren Sie es online aus.
Komprimiert nur perfekte Palindrome.
quelle