L'un des paradigmes de programmation les moins connus qui semble plutôt approprié pour le golf de code est Overlapping Oriented Programming (OOP) *. Lors de l'écriture de code partiellement identique, de nombreux octets peuvent être enregistrés en chevauchant simplement les parties identiques et en se souvenant d'une manière où les deux lignes de code d'origine commencent. Votre tâche consiste à écrire deux programmes ou fonctions qui se chevauchentcompress
et decompress
avec les spécifications suivantes:
* Ne pas utiliser dans le code de production, probablement.
compress
compress
prend deux chaînes dans n'importe quel format pratique et les chevauche autant que possible. C'est-à-dire qu'une chaîne s
de longueur minimale est renvoyée de telle sorte que les deux chaînes d'entrée sont des sous-chaînes de s
. De plus, une sortie identifiant les indices de début et de fin des deux chaînes est renvoyée.
Exemples: (Le format IO exact dépend de vous)
compress("abcd", "deab") -> "deabcd" ((2,5),(0,3))
compress("abcd", "bc") -> "abcd" ((0,3),(1,2))
compress("abc", "def") -> "abcdef" ((0,2),(3,5)) or "defabc" ((3,5),(0,2))
decompress
decompress
calcule la fonction inverse de compress
, qui est donnée une chaîne et deux indices de début et de fin (dans le format dans lequel ils sont retournés par votre compress
), renvoyer les deux chaînes d'origine. Vous n'avez besoin que de gérer des entrées valides. L'égalité suivante devrait tenir toutes les chaînes s1
, s2
:
(s1, s2) == decompress (compress (s1, s2))
Exemples: (inverses d' compress
exemples)
decompress "deabcd" ((2,5),(0,3)) -> "abcd" "deab"
decompress "abcd" ((0,3),(1,2)) -> "abcd" "bc"
decompress "abcdef" ((0,2),(3,5)) -> "abc" "def"
or (whichever version your "compress" generates)
decompress "defabc" ((3,5),(0,2)) -> "abc" "def"
Notation
Votre score est la taille de la chaîne retournée en appelant compress("<code of compress>", "<code of decompress>")
. Comme il s'agit de code-golf, un score inférieur est meilleur.
Exemple:
Supposons que le code de votre fonction compress
est c=abcd
et que le code de decompress
est d=efghi
. Ensuite, les compress("c=abcd", "d=efghi")
rendements "c=abcd=efghi"
(et les indices, mais ceux-ci n'affectent pas le score), le score est donc length "c=abcd=efghi" = 12
.
Règles supplémentaires
- Dans l'esprit de ce défi, votre
compress
etdecompress
doit se chevaucher dans au moins un caractère. Vous pouvez y parvenir de manière triviale en ajoutant un commentaire, mais notez que cela augmentera votre score et il pourrait y avoir des solutions plus courtes utilisant du code se chevauchant intrinsèquement. compress
etdecompress
devrait être capable de gérer les chaînes contenant tous les caractères ASCII imprimables ainsi que tous les caractères que vous avez utilisés pour définircompress
etdecompress
.- Les indices peuvent être indexés à zéro ou à un.
- Vos programmes ou fonctions n'ont pas besoin d'être nommés
compress
etdecompress
.
Réponses:
GNU Prolog, 105 points
(Cela nécessite GNU Prolog car
prefix
etsuffix
n'est pas portable.)Prolog a un avantage intéressant et majeur pour ce défi; vous pouvez écrire une fonction pour gérer plusieurs modèles d'appel (c.-à-d. non seulement vous pouvez donner à la fonction une entrée pour obtenir une sortie correspondante, vous pouvez donner à la fonction une sortie pour obtenir l'entrée correspondante). En tant que tel, nous pouvons définir une fonction qui peut gérer à la fois la compression et la décompression, conduisant à une soumission de 105 octets qui définit une fonction
o
qui fonctionne dans les deux sens. (Soit dit en passant, je l'ai principalement écrit en tant que décompresseur - car c'est plus simple - et j'ai obtenu le compresseur "gratuitement".) En général, nous pourrions nous attendre à un programme très court dans Prolog pour cette tâche, sinon pour le fait qu'il est si mauvais à la gestion des chaînes (à la fois en termes de primitives manquantes et en termes de primitives en question ayant des noms terriblement longs).Le premier argument de
o
est un tuple de chaînes, par exemple"abcd"-"deab"
. Le deuxième argument a une forme comme"deabcd"-4/6-4/4
; il s'agit d'un tuple imbriqué assez standard et signifie que la chaîne est "deabcd", la première chaîne a une longueur 4 et se termine au sixième caractère, la deuxième chaîne a une longueur 4 et se termine au quatrième caractère. (Notez qu'une chaîne dans GNU Prolog n'est qu'une liste de codes de caractères, ce qui rend le débogage ennuyeux car l'implémentation préfère la dernière interprétation par défaut.) Si vous donnezo
un argument, il produira l'autre pour vous (fonctionnant ainsi comme un compresseur si vous donnez le premier argument, et un décompresseur si vous donnez le second). Si vous lui donnez les deux arguments, il vérifiera que la représentation compressée correspond aux chaînes données. Si vous ne lui donnez aucun argument, il générera une sortie comme celle-ci:La description ci-dessus du format d'E / S est à peu près entièrement une description du programme également; il n'y a pas grand-chose dans le programme. La seule subtilité est liée aux conseils d'ordre d'évaluation; nous devons nous assurer que le programme n'utilise pas seulement une stratégie de recherche dont la fin est garantie, mais produit également la chaîne de sortie la plus courte possible.
Lors de la compression, nous commençons par
length(C,_)
("C
a une longueur"), ce qui est une astuce que j'ai utilisée dans de nombreuses réponses Prolog et Brachylog; si c'est la première chose que Prolog voit, cela lui fera prioriser la réduction de la longueur parC
rapport à toute autre chose. Cela garantit que nous avons une longueur minimaleC
. L'ordre des contraintes danss
est soigneusement choisi pour que la recherche prenne un temps fini pour chaque longueur possible de candidatC
;A
est contraint parC
(nous ne savons pasC
, mais nous connaissons la valeur cible que nous avons pour sa longueur),M
parA
,U
parA
etL
parU
, donc aucune des recherches ne peut prendre un temps illimité.Lors de la décompression, nous sommes donnés
C
directement par l'utilisateur. Cela garantit à nouveau que le programme fonctionnera en temps fini, en raison de la même séquence de contraintes. (Les personnes qui connaissent l'ordre d'évaluation de Prolog noteront que la définition des
est très inefficace lors de la décompression; le placementlength(A,M)
et lelength(U,L)
premier seraient plus rapides, mais le déplacementlength(A,M)
vers le début pourrait provoquer une boucle infinie lors de la compression car ni l'unA
ni l'autreM
n'est lié par quoi que ce soit à l'époque .)la source
Brachylog ,
5046 octetsEssayez-le en ligne!
Décompresser:
Essayez-le en ligne!
5 octets enregistrés grâce à @ ais523
Explication
Le bon côté des langages déclaratifs est que nous pouvons réutiliser le même code pour la compression et la décompression. En tant que tel, le code pour compresser est exactement le même que pour décompresser , avec un supplémentaire
~
au début.Cela
~
indique à Brachylog d'inverser l'ordre des arguments (c'est-à-dire d'utiliser l'entrée comme sortie et la sortie comme entrée). Puisque compress n'a pas~
, il exécute en fait le prédicat dans l'ordre standard. Comme la décompression n'en a qu'une seule, elle l'exécute avec l'entrée en sortie et la sortie en entrée.De cette façon, nous pouvons utiliser le même code (modulo that extra
~
) pour compresser et décompresser: la compression fournit les deux chaînes en entrée et une variable en sortie, et la décompression fournit les index et la chaîne compressée en sortie et une variable en entrée .Évidemment, cela signifie également que nous devons être un peu explicites sur notre code de compression, afin que l'interpréteur soit capable de l'exécuter "à l'envers". C'est pourquoi le compresseur lui-même est un peu long.
Voici une ventilation du code pour Compress (et donc aussi de décompresser):
la source
Gelée ,
5850 octets-1 octet grâce à ais523 (à utiliser
⁾
pour une chaîne de deux octets)Cela peut être assez golfable ...
La compression prend deux arguments de chaîne et renvoie une liste:
[[[startA, lengthA], [startB, lengthB]], compressedString]
La décompression prend un argument (une telle liste) et renvoie deux chaînes *:
Code superposé:
Un index.
* cela peut ne pas être évident en raison de la mise en forme d'impression implicite de Jelly, donc le code de TryItOnline lié à ci-dessus a un octet supplémentaire (un
Y
à la fin) pour insérer un saut de ligne entre les deux dans la sortie imprimée.J'ai commencé avec un seul programme, qui utilisait la profondeur du premier (ou unique) argument pour décider entre la compression et la décompression, mais ayant un lien inutilisé dans le code de décompression (la première ligne) et un seul octet se chevauchant est plus court de sept octets .
Comment?
la source
“ṫḣ”
peut être joué sur 1 octet en utilisant la syntaxe de Jelly pour les chaînes de 2 caractères.