Défi
Écrivez un programme qui compresse et décompresse le texte ASCII sans perte. Il devrait être spécialisé pour bien fonctionner avec les palindromes, y compris les palindromes insensibles à la casse et à la ponctuation. La meilleure compression avec la plus petite source gagne.
Notation
total_bytes_saved / sqrt(program_size)
- Le score le plus élevé gagne
total_bytes_saved
est le nombre d'octets plus petit que les chaînes compressées sont que les originaux, total dans les cas de test ci-dessous. program_size
est la taille en octets du code source des programmes de compression et de décompression. Le code partagé entre les deux ne doit être compté qu'une seule fois.
Par exemple, s'il y a 10 cas de test et qu'un programme de 100 octets a enregistré 5 octets sur 7 cas de test, 10 chacun sur 2 d'entre eux, mais que le dernier cas de test avait 2 octets de plus, la solution obtiendrait 5,3. ( (7 * 5 + 10 * 2 - 2) / sqrt(100) = 5.3
)
Cas de test
tacocat
toohottohoot
todderasesareddot
amanaplanacanalpanama
wasitacaroracatisaw?
Bob
IManAmRegalAGermanAmI
DogeeseseeGod
A Santa at NASA
Go hang a salami! I'm a lasagna hog.
Règles
- Des échappatoires standard s'appliquent.
- La compression doit fonctionner sur toutes les chaînes de texte ASCII imprimables (octets 32 à 126 inclus), pas seulement sur les palindromes. Cependant, il n'a pas besoin d'économiser de l'espace pour les entrées.
- La sortie peut être n'importe quelle séquence d'octets ou de caractères, quelle que soit sa mise en œuvre ou sa représentation interne (les chaînes, les listes et les tableaux sont tous des jeux équitables, par exemple). Si vous encodez en UTF-8, comptez les octets, pas les caractères. Les chaînes larges (par exemple UTF-16 ou UTF-32) ne sont pas autorisées à moins que les seuls points de code éventuellement utilisés soient compris entre 0 et 255.
- Les commandes internes de compression / décompression ne sont pas autorisées.
Pour notre plus grand plaisir, postez les chaînes compressées avec votre code source.
MISE À JOUR 1: La notation est passée de total_bytes_saved / program_size
à total_bytes_saved / sqrt(program_size)
afin de donner plus de poids à une meilleure compression et moins de poids au golf agressif. Ajustez vos scores en conséquence.
MISE À JOUR 2: corrigé wasitacaroraratisaw?
pour êtrewasitacaroracatisaw?
la source
wasitacaroraratisaw?
c'est un contre-exemple à cela[32-126]
?1000 *
partie soit vraiment nécessaire, et non je ne pense pas que cela rendra le score plus "satisfaisant";)Réponses:
JavaScript (ES6), 3.143 (81 octets enregistrés, programme de 664 octets)
Maintenant que je suis assez satisfait de ce programme (et du système de notation), je vais écrire une petite explication.
L'idée de base est de compresser l'entrée en une chaîne de bits, puis de compresser chaque ensemble de 8 bits en un octet. Aux fins d'explication, je vais simplement manipuler la chaîne de bits.
La chaîne de bits peut être séparée en plusieurs sections:
L'en-tête est un mappage très simple:
Les données de lettres sont également assez simples. Tout d'abord, toutes les non-lettres sont extraites de la chaîne et toutes les lettres sont converties en majuscules. Si la chaîne résultante est un palindrome, la moitié inversée est supprimée. Ensuite, ce mappage est appliqué:
Cette section se termine par
111
. Après cela viennent les données de style, qui stockent les données majuscules / minuscules et les non-lettres. Cela fonctionne comme ceci:Donc, en passant par l'exemple ci-dessus, nous avons
Lorsque la fin de la chaîne de bits est atteinte, tous les caractères restants des données de lettre sont ajoutés au résultat. Cela nous évite d'avoir à faire un dernier
000...001
et nous permet de tronquer ces bits de la chaîne.En passant par les cas de test:
la source
Bob
.Bob
vraiment juste mis en place - 1 bit pour l'en-tête, 10 + 3 bits pour les deux lettres et 2 bits pour la lettre majuscule unique. Je ne pourrais pas le raccourcir si j'essayais de mon-0+9
+9
serait concaténé à la chaîne, tandis que-~8
ferait+9
arithmétiquement (puisque-
ne fait rien pour les chaînes, donc il l'interprète comme un nombre). Dans ce cas,-~8
c'est assez intelligent. :) Belle réponse btw, +1 de ma part! Très intelligent stockant toutes les informations dans des bits comme ça, même en économisant un octetBob
.Python 2: 2,765 (70 octets enregistrés, programme 641 octets)
J'ai un peu changé mon approche. Il fonctionne désormais bien sur les palindromes imparfaits. Aucune chaîne compressée ne sera plus longue que l'entrée. Des palindromes parfaits de longueur uniforme comprimeront toujours à 50% la taille d'origine.
Résultats
Et en bonus, il économise 6 octets sur mon palindrome incorrect que j'avais auparavant.
Explication
La décompression utilise une pile. Les points de code de 32 à 127 sont traités littéralement. Si un caractère est une lettre, une valeur est également insérée dans la pile. Les valeurs 128-192 sont utilisées pour les lettres retournées par la casse, de sorte que la lettre enfoncée dans le cas (en
o^32
raison de la disposition de l'ASCII) est poussée dans la pile et la lettre normale est ajoutée à la chaîne. Les valeurs 192-255 sont utilisées pour ajouter des lettres sans pousser vers la pile, donc cela est utilisé lorsque les lettres ne correspondent pas et pour la lettre du milieu dans les palindromes de longueur impaire. Les points de code 1 à 15 indiquent que la pile doit être sautée autant de fois. Les points de code 17 à 31 sont similaires, mais ils impriment d'abord un espace avant de sortir de la pile. Il y a aussi une instruction implicite "pop jusqu'à vide" à la fin d'une entrée.Le compresseur fonctionne des deux extrémités et se plie en lettres correspondantes en tant que valeurs 1-31. Il saute les non-lettres. Lorsque les lettres correspondent, mais pas la casse, il ajoute 64 à la lettre de gauche et incrémente la lettre de droite. Cela lui permet d'économiser de l'espace
IManAmRegalAGermanAmI
. Au milieu ou lorsque les lettres ne correspondent pas, il est 128 des deux côtés. Je ne peux pas y ajouter car je dois éviter le cas spécial oùleft == right
. Lors du pliage des marqueurs pop voisins sur le côté droit, je dois vérifier que le marqueur voisin ne débordera pas dans le point de code 16 car j'en ai besoin pour les espaces. (Ce n'est en fait un problème pour aucune des chaînes de scénario de test)EDIT 1 : Plus de version non golfée.
la source
Python3, 1,833 (25 octets enregistrés, programme de 186 octets)
Codage entropique à probabilité égale d'ordre 0 simple. Aucune optimisation spécifique au palindrome.
la source
Java 8, score: 1,355 (20 octets enregistrés / 218 (107 + 111) octets)
Fonction de compression (contient trois caractères ASCII non imprimables):
Fonction de décompression (contient deux caractères ASCII non imprimables):
Explication:
Essayez-le en ligne.
Compresse uniquement les palindromes parfaits.
la source