ASCII 아트를 그리기 위해 RLE 데이터 압축


11

이 질문은 내가 다른 질문 에 대답하기 위해 생각 해낸 것에 근거합니다 .

때때로 여기의 질문은 ASCII 아트를 그리는 것을 요구합니다. 해당 기술에 대한 데이터를 저장하는 간단한 방법 중 하나는 RLE (run-length encoding) 입니다. 그래서:

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)

마지막으로 일부 문자 (기호 + 기호)가 반복되는 것을 알 수 있으므로 문자열에서 3 번 이상 나타나는 그룹을 문자열의 순서 또는 모양으로 소문자 문자 집합으로 대체하지만 버퍼에 저장하면 대체 (각 대체에 대해 "group + substitution char"형식으로)하고 나머지 문자열은 그대로 둡니다. 따라서 다음 그룹은

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

26 개를 초과하는 그룹이 반복되지 않으므로 'a', 'b'및 'c'로 각각 대체됩니다. 마지막으로 다음을 얻습니다.

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

(Character count: 9+24=33)

[마지막 단계 후에 문자를 실제로 저장하는 그룹이 4 번 이상 나타나는 그룹이므로 마지막 단계는 1 바이트 만 절약합니다.]

도전

ASCII 아트를 그리기위한 RLE 데이터가 포함 된 문자열이 제공되면 (제한이 제 안됨) 설명 된대로 압축하기 위해 가능한 가장 짧은 프로그램 / 함수 / 방법을 작성하십시오. 알고리즘은 두 문자열을 인쇄 / 반환해야합니다. 첫 번째 문자열은 압축에 사용 된 사전을 포함하고 두 번째 문자열은 압축 된 문자열입니다. 주어진 순서대로 문자열을 Tuple, 배열, List 또는 기타로 반환 할 수 있습니다.

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
캐릭터 Nope를 26 회 이상 반복하지 않기 때문 입니다. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Okx

@Okx 그것은 결코 사실이 아닙니다.
Outgolfer Erik

@Okx 예, 현실 세계에서. 그러나 규칙은 제한된 ASCII 아트 세트로 구성됩니다.
Charlie

2
실제 구현에서는 S,aT bK@c아마도 S,T K@그로부터 사소하게 추론 될 수있는 대체 문자의 이름을 명시 적으로 지정하지 않고 그대로 저장됩니다 .
Arnauld 2016 년

@ Arnauld 당신이 완전히 맞아요, 나는 그것을 놓쳤습니다. 그러나 누군가가 자신의 대답을 쓰기 시작했을 때를 대비하여 질문을 그대로 남겨 두겠습니다.
Charlie

답변:


3

자바 스크립트 (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

파이썬 (2) , 269 (280) 268 266 바이트

여기서 멋진 일이 없습니다. 간단한 정규 표현식을 사용할 수있는 좋은 기회입니다.

정규식 내에서 해석 된 특수 문자가 포함 된 문자열의 경우 첫 번째 버전이 실패했습니다. 두 번째 버전 (re.escape 사용)은 모든 테스트 사례에서 작동합니다. 수정 비용은 11 바이트입니다.

두 번째 버전은 문제 사양에 필요하고 @CarlosAlejo가 지적한대로 대체 문자를 순서대로 할당하지 않았습니다. 다시 그리기 보드로 돌아갑니다.

수정 된 버전, 추가 골프

  • 두 줄로 출력을 인쇄하지 않아서 -6 바이트 절약
  • +3 바이트 : 문자열을 통해 코드 대체로 전환하여 지정된대로 챌린지를 충족시킬 수 있습니다.
  • -4 바이트 : 더 이상 re.findall을 두 번 호출하지 않으므로 이름을 바꿀 필요가 없습니다.
  • -5 바이트 : for 루프에서 while 루프로 전환.
  • @Comrade Sparkle Pony 덕분에 -2 바이트
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.
Charlie

@CarlosAlejo 필자는 기능적 관점에서 대체가 임의적이므로 요구 사항으로 언급하지 않았습니다. 이것을 구현하는 자연스러운 방법 인 파이썬의 기본 사전은 순서가 없습니다. 다른 가능한 데이터 구조를 고려해야합니다 ....
CCB60

b=a=input()n,s,p=96,'',0? 를 사용하여 일부 바이트를 저장할 수 없습니다 .
동지 SparklePony

\d+사용하는 정규식이 더 짧을 것입니다. 당신은 어쨌든 26을 넘지 않을 것이므로 특별히 1-2 자리인지 확인할 이유가 없습니다. 또한을 사용 re.escape하면 기본 문자열 replace이 약간 짧아집니다. 253 바이트
Value Ink

0

루아, 215 바이트

좋은 패턴 일치.

골프에 관해서는 루아가 과소 평가 된 것 같아요.

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

파이썬 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 단계에서 압축되지 않음


파이썬 2 , 246 바이트

repl 람다에서 수행되는 전체 제 2 단계. 재미로.

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

온라인으로 사용해보십시오!



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.