Nén dữ liệu RLE để vẽ nghệ thuật ASCII


11

Câu hỏi này dựa trên những gì tôi nghĩ ra để trả lời một câu hỏi khác .

Đôi khi các câu hỏi ở đây yêu cầu vẽ một số nghệ thuật ASCII. Một cách đơn giản để lưu trữ dữ liệu cho nghệ thuật là RLE (mã hóa độ dài chạy) . Vì thế:

qqqwwwwweeerrrrrtttyyyy

trở thành:

3q5w3e5r3t4y

Bây giờ để vẽ một nghệ thuật ASCII lớn, bạn có thể nhận được dữ liệu như thế này (bỏ qua các ký tự dòng mới):

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)

Các ký tự được sử dụng cho nghệ thuật ASCII sẽ không bao giờ là chữ thường hoặc chữ in hoa hoặc số, chỉ ký hiệu, dấu hiệu và ký hiệu mà luôn nằm trong bộ ký tự ASCII có thể in được.

Bạn muốn tiết kiệm một số khoảng trống trong chuỗi đó, vì vậy bạn thay thế các số bằng bộ ký tự viết hoa (là 'A' bằng 1, 'B' bằng 2 cho đến khi 'Z' bằng 26), bởi vì bạn sẽ không bao giờ nhận được hơn 26 lần lặp lại của một nhân vật. Vì vậy, bạn nhận được:

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

(Character count: 34)

Và cuối cùng bạn nhận thấy rằng một số nhóm (ký tự + ký hiệu) đang lặp lại, vì vậy bạn thay thế các nhóm xuất hiện 3 lần trở lên trong chuỗi bằng bộ ký tự chữ thường, theo thứ tự hoặc xuất hiện trong chuỗi, nhưng lưu trữ trong bộ đệm thay thế được thực hiện (theo định dạng "nhóm + char thay thế" cho mỗi lần thay thế) và để lại phần còn lại của chuỗi. Vì vậy, các nhóm sau:

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

được thay thế bằng 'a', 'b' và 'c', bởi vì sẽ không bao giờ có quá 26 nhóm lặp lại. Vì vậy, cuối cùng bạn nhận được:

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

(Character count: 9+24=33)

[Bước cuối cùng chỉ lưu 1 byte vì các nhóm thực sự lưu ký tự sau khi được thay thế là nhóm xuất hiện 4 lần trở lên.]

Các thách thức

Đưa ra một chuỗi chứa dữ liệu RLE để vẽ một nghệ thuật ASCII (với các hạn chế được đề xuất), hãy viết chương trình / hàm / phương thức ngắn nhất bạn có thể để nén nó như mô tả. Thuật toán phải in / trả về hai chuỗi: chuỗi đầu tiên chứa từ điển được sử dụng để nén và chuỗi thứ hai là chuỗi nén kết quả. Bạn có thể trả về các chuỗi dưới dạng Tuple, một mảng, Danh sách hoặc bất cứ thứ gì, theo thứ tự đã cho.

Lưu ý rằng nếu chuỗi không thể được nén trong bước 2, thuật toán phải trả về một chuỗi trống là giá trị trả về đầu tiên và kết quả của bước 1 là giá trị trả về thứ hai.

Bạn không cần đưa kết quả của bước 1 vào các giá trị đầu ra, tôi chỉ đưa chúng vào các ví dụ cho mục đích làm rõ.

Đây là , vì vậy có thể câu trả lời ngắn nhất cho mỗi ngôn ngữ sẽ giành chiến thắng!

Một trường hợp thử nghiệm

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
bởi vì bạn sẽ không bao giờ nhận được hơn 26 lần lặp lại của một nhân vật Nope. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Okx

@Okx Điều đó không bao giờ có thể xảy ra.
Erik the Outgolfer

@Okx vâng, trong thế giới thực. Các quy tắc được tạo thành cho một bộ hạn chế của nghệ thuật ASCII.
Charlie

2
Trong một triển khai thực tế, S,aT bK@ccó lẽ sẽ được lưu trữ như là S,T K@không có tên rõ ràng các ký tự thay thế có thể được suy luận tầm thường từ đó.
Arnauld

@Arnauld bạn hoàn toàn đúng, tôi đã bỏ lỡ điều đó, nhưng tôi sẽ để lại câu hỏi như vậy, chỉ trong trường hợp bất cứ ai đã bắt đầu viết câu trả lời của anh ấy / cô ấy.
Charlie

Câu trả lời:


3

JavaScript (ES6), 168 167 byte

Trả về một mảng gồm hai chuỗi : [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``]

Các trường hợp thử nghiệm


3

Python 2 , 269 280 268 266 byte

Không có gì lạ mắt xảy ra ở đây. Cơ hội tốt để sử dụng một số biểu thức chính quy đơn giản.

Phiên bản đầu tiên thất bại đối với các chuỗi chứa các ký tự đặc biệt được diễn giải trong biểu thức chính quy. Phiên bản thứ hai (sử dụng re.escape) hoạt động với tất cả các trường hợp thử nghiệm. Điều chỉnh đó có giá 11 byte.

Phiên bản thứ hai không chỉ định các ký tự thay thế theo thứ tự, theo yêu cầu trong đặc tả vấn đề và như được chỉ ra bởi @CarlosAlejo. Vì vậy, trở lại bảng vẽ.

Phiên bản sửa chữa, đánh gôn thêm

  • -6 byte được lưu bằng cách không in đầu ra trên hai dòng
  • +3 byte: Chuyển sang thay thế mã thông qua một chuỗi để cho phép đáp ứng thách thức theo quy định.
  • -4 byte: Vì tôi không còn gọi re.findall hai lần nữa, tôi không cần đổi tên nó
  • -5 byte: chuyển từ vòng lặp sang vòng lặp while.
  • -2 byte nhờ @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

Hãy thử trực tuyến!


Bạn sắp hoàn thành, lưu ý rằng các nhóm trong bước thứ hai không được tạo theo thứ tự thích hợp (xem ví dụ). Các nhóm phải được tạo theo thứ tự xuất hiện, vì vậy nhóm đầu tiên phải là O,a.
Charlie

@CarlosAlejo Tôi đã không lưu ý rằng như một yêu cầu, vì sự thay thế là tùy ý, từ quan điểm chức năng. Từ điển mặc định của Python, một cách tự nhiên để thực hiện điều này, không có thứ tự. Sẽ phải xem xét các cấu trúc dữ liệu có thể khác ....
CCB60

Bạn không thể lưu một số byte bằng cách sử dụng b=a=input()n,s,p=96,'',0?
Đồng chí SparklePony

\d+sẽ là một regex ngắn hơn để sử dụng. Bạn sẽ không bao giờ vượt quá 26 dù sao, vì vậy không có lý do gì để đảm bảo rằng đó là 1-2 chữ số cụ thể. Ngoài ra, sử dụng re.escapecó nghĩa là một chuỗi cơ bản replacekết thúc ngắn hơn một chút: 253 byte
Giá trị mực

0

Lua, 215 byte

Chỉ cần một chút phù hợp với mô hình.

Tôi nghĩ rằng Lua bị đánh giá thấp khi nói đến việc chơi golf ... hãy nhìn vào tất cả những tuyên bố đó được ghép lại với nhau!

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 byte

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

Tôi đã hy vọng cuối cùng tìm thấy sử dụng cho 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

Nén ở bước 2

Không được nén ở bước 2


Python 2 , 246 byte

Toàn bộ bước thứ hai được thực hiện trong thay thế lambda của re.sub. Chỉ để cho vui.

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

Hãy thử trực tuyến!


0

Perl 5 -pl , 81 byte

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

Hãy thử trực tuyến!

In chuỗi được mã hóa trên dòng đầu tiên, bộ ba trên dòng thứ hai


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.