Compression des données RLE pour dessiner de l'art ASCII

11

Cette question est basée sur ce que j'ai trouvé pour répondre à une autre question .

Parfois, les questions ici demandent de dessiner de l'art ASCII. Un moyen simple de stocker les données pour l'art est RLE (encodage de longueur) . Donc:

qqqwwwwweeerrrrrtttyyyy

devient:

3q5w3e5r3t4y

Maintenant, pour dessiner un grand art ASCII, vous obtiendrez peut-être des données comme celle-ci (en ignorant les nouveaux caractères de ligne):

19,20 3(4)11@1$20 11@19,15"4:20 4)19,4:20 11@
   ^^^
   Note that this is "20 whitespaces"

(Character count: 45)

Les caractères utilisés pour l'art ASCII ne seront jamais des lettres ou des chiffres minuscules ou majuscules, seulement des signes, des marques et des symboles mais toujours dans le jeu de caractères ASCII imprimable.

Vous voulez économiser de l'espace dans cette chaîne, donc vous remplacez les nombres par le jeu de caractères majuscules (étant 'A' est égal à 1, 'B' est égal à 2 jusqu'à ce que 'Z' soit égal à 26), parce que vous n'allez jamais obtenir plus de 26 répétitions d'un personnage. Vous obtenez donc:

S,T C(D)K@A$T K@S,O"D:T D)S,D:T K@

(Character count: 34)

Et enfin, vous remarquez que certains groupes de (lettre + symbole) se répètent, vous remplacez donc les groupes qui apparaissent 3 fois ou plus dans la chaîne par le jeu de caractères en minuscules, dans l'ordre ou l'apparence dans la chaîne, mais en stockant dans un tampon le substitutions effectuées (au format "groupe + caractère de substitution" pour chaque substitution) et en laissant le reste de la chaîne tel quel. Donc les groupes suivants:

S, (3 times) 
T  (4 times)
K@ (3 times)

est remplacé par «a», «b» et «c», respectivement, car il n'y aura jamais plus de 26 groupes se répétant. Donc, finalement, vous obtenez:

S,aT bK@c
abC(D)cA$bcaO"D:bD)aD:bc

(Character count: 9+24=33)

[La dernière étape enregistre seulement 1 octet car les groupes qui enregistrent réellement les caractères après avoir été substitués sont ceux qui apparaissent 4 fois ou plus.]

Le défi

Étant donné une chaîne contenant les données RLE pour dessiner un art ASCII (avec les restrictions proposées), écrivez le programme / fonction / méthode le plus court possible afin de le compresser comme décrit. L'algorithme doit imprimer / renvoyer deux chaînes: la première contenant le dictionnaire utilisé pour la compression et la seconde étant la chaîne compressée résultante. Vous pouvez renvoyer les chaînes sous la forme d'un tuple, d'un tableau, d'une liste ou autre, dans l'ordre donné.

Notez que si la chaîne ne peut pas être compressée à l'étape 2, l'algorithme doit renvoyer une chaîne vide comme première valeur de retour et le résultat de l'étape 1 comme deuxième valeur de retour.

Vous n'avez pas besoin d'inclure le résultat de l'étape 1 dans les valeurs de sortie, je les inclue simplement dans les exemples à des fins de clarification.

C'est , alors la réponse la plus courte pour chaque langue peut gagner!

Un autre cas de test

Input:                   15,15/10$15,15/10"10$10"10$10"10$10"15,15/

Output of step 1:        O,O/J$O,O/J"J$J"J$J"J$J"O,O/

Final algorithm output:  O,aO/bJ$cJ"d
                         abcabdcdcdcdab

---

Input:                   15,15/10$15,15/10"

Output of step 1:        O,O/J$O,O/J"

Final algorithm output:  <empty string>
                         O,O/J$O,O/J"
Charlie
la source
1
parce que vous n'obtiendrez jamais plus de 26 répétitions d'un personnage Non. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Okx
@Okx Cela ne peut jamais être le cas.
Erik the Outgolfer
@Okx oui, dans le monde réel. Les règles sont cependant conçues pour un ensemble restreint d'œuvres d'art ASCII.
Charlie
2
Dans une implémentation réelle, S,aT bK@cserait probablement stocké comme juste S,T K@sans nommer explicitement les caractères de substitution qui peuvent être trivialement déduits de cela.
Arnauld
@Arnauld vous avez tout à fait raison, cela m'a manqué, mais je vais laisser la question telle quelle, juste au cas où quelqu'un aurait commencé à écrire sa réponse.
Charlie

Réponses:

3

JavaScript (ES6), 168 167 octets

Renvoie un tableau de deux chaînes: [dictionary, compressed_string].

s=>[(a=(s=s.replace(/\d+/g,n=>C(n|64),C=String.fromCharCode)).match(/../g)).map(v=>s.split(v)[a[v]||3]>=''?D+=v+(a[v]=C(i++)):0,i=97,D='')&&D,a.map(v=>a[v]||v).join``]

Cas de test

Arnauld
la source
3

Python 2 , 269 280 268 266 octets

Rien de spécial ici. Bonne occasion d'utiliser des expressions régulières simples.

La première version a échoué pour les chaînes contenant des caractères spéciaux qui ont été interprétés dans l'expression régulière. La deuxième version (utilisant re.escape) fonctionne avec tous les cas de test. Cette correction a coûté 11 octets.

La deuxième version n'a pas attribué de caractères de substitution dans l'ordre, comme requis dans la spécification du problème, et comme l'a souligné @CarlosAlejo. Revenons donc à la planche à dessin.

Version corrigée, encore golfée

  • -6 octets enregistrés en n'imprimant pas la sortie sur deux lignes
  • +3 octets: Passer aux substitutions de code via une chaîne pour permettre de relever le défi comme spécifié.
  • -4 octets: comme je n'appelle plus deux fois re.findall, je n'ai pas besoin de le renommer
  • -5 octets: passage des boucles for aux boucles while.
  • -2 octets grâce à @Comrade Sparkle Pony
import re
S=re.sub
b=a=input()
for i in re.findall('\d{1,2}',a):
 b=S(i, chr(64+int(i)),b)
n,s,p=96,'',0
while p<len(b):
 c=b[p:p+2];f=b.count(c)
 if f>2and not c in s:n+=1;s+=c+chr(n)
 p+=2
p=0
while p<len(s):k=s[p:p+2];v=s[p+2];b=S(re.escape(k),v,b);p+=3
print s,b

Essayez-le en ligne!

CCB60
la source
Vous y êtes presque, notez que les groupes de la deuxième étape ne sont pas créés dans le bon ordre (voir exemple). Les groupes doivent être créés par ordre d'apparition, donc le premier devrait l'être O,a.
Charlie
@CarlosAlejo Je n'avais pas noté cela comme une exigence, puisque les substitutions sont arbitraires, d'un point de vue fonctionnel. Les dictionnaires par défaut de Python, un moyen naturel de l'implémenter, ne sont pas ordonnés. Devra considérer d'autres structures de données possibles ....
CCB60
Ne pourriez-vous pas enregistrer certains octets en utilisant b=a=input()et n,s,p=96,'',0?
Camarade SparklePony
\d+serait une expression rationnelle plus courte à utiliser. Vous ne dépasserez jamais 26 de toute façon, il n'y a donc aucune raison de s'assurer que c'est spécifiquement 1-2 chiffres. En outre, l'utilisation re.escapesignifie qu'une chaîne de base replacese termine légèrement plus courte: 253 octets
Value Ink
0

Lua, 215 octets

Juste un peu de correspondance de motifs.

Je pense que Lua est sous-estimée quand il s'agit de jouer au golf ... regardez toutes ces déclarations écrasées ensemble!

g,c=string.gsub,string.char
u=g(arg[1],"%d%d?",function(n)return c(n+64)end)l,d=97,""g(u,"..",function(m)n,e=0,g(m,".", "%%%0")g(u,e,function()n=n+1 end)if n>2 then
l,s=l+1,c(l)d,u=d..m..s,g(u,e,s)end
end)print(u,d)
Trébuchette
la source
0

Python 2 , 186 octets

from re import*
S=sub('\d+',lambda m:chr(int(m.group(0))+64),input())
Q=[]
for p in findall('[A-Z].',S):
 if S.count(p)>2:a=chr(len(Q)+97);Q+=[p+a];S=sub(escape(p),a,S)
print''.join(Q),S

J'espérais enfin trouver une utilisation pour re.subn: C

# first step - convert all numbers to uppercase letters
S=sub('\d+',lambda m:chr(int(m.group(0))+64),input())
# empty list to hold encoding of second step
Q=[]
# find every encoded pair (uppercase letter and some char)
for p in findall('[A-Z].',S):
 # if it occures 3 or move times
 if S.count(p)>2:
  # get lowercase letter to substitute with
  a=chr(len(Q)+97)
  # store encoding into list
  Q+=[p+a]
  # update string - substitute pair with lowercase letter
  S=sub(escape(p),a,S)
# output
# encodings of second step, space, result
# if nothing was compressed at step 2, space would prepend result (of step 1)
print''.join(Q),S

Compressé à l'étape 2

Non compressé à l'étape 2


Python 2 , 246 octets

Toute la deuxième étape se fait en repl lambda de re. Juste pour le fun.

from re import*
Q=[]
S=sub('\d+',lambda m:chr(int(m.group(0))+64),input())
S=sub('[A-Z].',lambda m:(lambda m:S.count(m)>2and(m in Q or not Q.append(m))and chr(Q.index(m)+97)or m)(m.group(0)),S)
print''.join(Q[i]+chr(i+97)for i in range(len(Q))),S

Essayez-le en ligne!

Possum mort
la source
0

Perl 5 -pl , 81 octets

s/\d+/chr$&+64/ge;$b=a;for$a(/([A-Z].)(?=.*\1.*\1)/g){s/\Q$a/$b/g&&($\.=$a.$b++)}

Essayez-le en ligne!

Imprime la chaîne encodée sur la première ligne, les triplets sur la deuxième ligne

Xcali
la source
0

Rubis -p , 133 octets

gsub(/(\d+)(.)/){(64+$1.to_i).chr+$2}
c=?`;s=''
$_.scan(/(..)(?=.*\1.*\1)/){s+=$&+c.succ!if !s[$&]}
puts s.scan(/(..)(.)/){gsub$1,$2}

Essayez-le en ligne!

Encre de valeur
la source