压缩RLE数据以绘制ASCII图形


11

这个问题是基于什么我想出了回答另一个问题

有时,这里的问题要求画一些ASCII艺术。一种用于存储数据的简单方法是RLE(行程编码)。所以:

qqqwwwwweeerrrrrtttyyyy

变成:

3q5w3e5r3t4y

现在,要画出很大的ASCII艺术,您可能正在获取如下数据(忽略换行符):

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)

用于ASCII艺术的字符永远不会是小写或大写字母或数字,而只能是符号,标记和符号,而总是在可打印的ASCII字符集中。

您想在该字符串中节省一些空间,所以用大写字符集替换数字(“ A”等于1,“ B”等于2,直到“ Z”等于26),因为您永远不会重复一个角色超过26次。这样就得到:

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

(Character count: 34)

最后,您注意到某些(letter + symbol)组正在重复,因此您将在字符串中出现3次或多次的组替换为小写字符集(按顺序或出现在字符串中,但将其存储在缓冲区中)进行替换(每次替换的格式为“ group + substitution char”),其余字符串保持原样。所以以下几组:

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

分别用“ a”,“ b”和“ c”代替,因为重复的组永远不会超过26个。所以最终您得到:

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

(Character count: 9+24=33)

[最后一步只保存1个字节,因为被替换后实际保存字符的组是出现4次或更多的组。]

挑战

给定一个包含RLE数据的字符串以绘制ASCII文字(提出了限制),请编写最短的程序/函数/方法,以便按说明进行压缩。该算法必须打印/返回两个字符串:第一个字符串包含用于压缩的字典,第二个字符串是生成的压缩字符串。您可以按给定的顺序将字符串作为元组,数组,列表或其他形式返回。

请注意,如果在步骤2中无法压缩字符串,则算法必须返回一个空字符串作为第一个返回值,并将步骤1的结果作为第二个返回值。

您无需在输出值中包含步骤1的结果,仅出于说明目的将它们包含在示例中。

这是,所以每种语言的最短答案可能会获胜!

另一个测试案例

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"

1
因为您永远不会获得超过26次重复的角色 Nope。aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Okx

@Okx永远不会这样。
暴民埃里克(Erik the Outgolfer)

@Okx是的,在现实世界中。但是,这些规则是由一组受限的ASCII艺术构成的。
查理

2
在一个实际的实现中,S,aT bK@c可能会被存储为只是S,T K@没有明确命名可以从中得出的替换字符。
Arnauld

@Arnauld你是完全正确的,我很想念,但是我将保留这个问题,以防万一有人开始写他/她的答案。
查理

Answers:


3

的JavaScript(ES6),168个 167字节

返回包含两个字符串的数组:[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``]

测试用例


3

Python 2中269个 280 268 266字节

这里没有幻想。使用一些简单的正则表达式的好机会。

对于包含在正则表达式中解释的特殊字符的字符串,第一个版本失败。第二版(使用re.escape)适用于所有测试用例。该校正花费11个字节。

第二版未按照问题规范中的要求,也未按照@CarlosAlejo的要求顺序分配替换字符。因此,回到绘图板。

更正版本,进一步打高尔夫球

  • 通过不在两行上打印输出来节省-6个字节
  • +3字节:通过字符串切换为代码替换,以允许满足指定的要求。
  • -4个字节:由于我不再调用re.findall两次,因此无需重命名
  • -5字节:从for循环切换到while循环。
  • -2个字节,感谢@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

在线尝试!


您快到了,请注意,第二步中的组未按正确的顺序创建(请参见示例)。必须按出现顺序创建组,因此第一个组应该是O,a
查理

@CarlosAlejo从功能的角度来看,我没有指出这是必需的,因为替换是任意的。Python的默认字典是实现此目的的自然方法,是无序的。将不得不考虑其他可能的数据结构
。...– CCB60

您不能使用b=a=input()和保存一些字节n,s,p=96,'',0吗?
“ SparklePony同志” 17年

\d+将是使用更短的正则表达式。无论如何,您永远都不会超过26,因此没有理由确保它是1-2位数字。同样,使用re.escape表示基本字符串的replace结尾稍微短一些:253个字节
Value Ink

0

Lua,215个字节

只是很多模式匹配。

我认为Lua在打高尔夫球时被低估了……看看所有那些相互挤压的陈述!

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)

0

Python 2,186字节

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

我希望最终可以用于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

在步骤2压缩

在第2步未压缩


Python 2,246个字节

整个第二步都在re.sub的repl lambda中完成。纯娱乐。

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

在线尝试!


0

Perl -pl 5,81个字节

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

在线尝试!

在第一行打印编码的字符串,在第二行打印三元组


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.