การบีบอัดข้อมูล 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)

และในที่สุดคุณก็สังเกตเห็นว่าบางกลุ่มของ (ตัวอักษร + สัญลักษณ์) กำลังทำซ้ำดังนั้นคุณจึงแทนที่กลุ่มที่ปรากฏ 3 ครั้งขึ้นไปในสตริงด้วยชุดอักขระตัวพิมพ์เล็กตามลำดับหรือลักษณะที่ปรากฏในสตริง แต่เก็บไว้ในบัฟเฟอร์ การแทนที่ที่เกิดขึ้น (ในรูปแบบ "กลุ่ม + การแทนที่ถ่าน" สำหรับการทดแทนแต่ละครั้ง) และปล่อยให้ส่วนที่เหลือของสตริงตามที่เป็นอยู่ ดังนั้นกลุ่มต่อไปนี้:

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 (โดยมีข้อ จำกัด ที่เสนอ) เขียนโปรแกรม / ฟังก์ชัน / วิธีที่สั้นที่สุดที่คุณสามารถทำได้เพื่อบีบอัดตามที่อธิบายไว้ อัลกอริทึมต้องพิมพ์ / ส่งคืนสองสาย: อันแรกที่มีพจนานุกรมที่ใช้สำหรับการบีบอัดและอันที่สองเป็นสายอักขระการบีบอัดผลลัพธ์ คุณสามารถส่งคืนสตริงเป็น Tuple, array, 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
เพราะคุณจะไม่ได้รับซ้ำมากกว่า 26 อักขระ Nope aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Okx

@Okx นั่นไม่สามารถเป็นได้
Erik the Outgolfer

@ อ็อกซ์ใช่แล้วในโลกแห่งความเป็นจริง แม้ว่ากฎจะถูกสร้างขึ้นสำหรับชุด ASCII art ที่ถูก จำกัด
Charlie

2
ในการนำไปปฏิบัติจริงS,aT bK@cอาจถูกเก็บไว้S,T K@โดยไม่มีการตั้งชื่ออักขระการแทนที่ซึ่งสามารถอนุมานได้เล็กน้อยจากนั้น
Arnauld

@Arnauld คุณถูกต้องทั้งหมดฉันพลาดไป แต่ฉันจะทิ้งคำถามตามที่เป็นอยู่ในกรณีที่มีใครเริ่มเขียนคำตอบของเขา / เธอ
Charlie

คำตอบ:


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 ไบต์

ไม่มีอะไรแฟนซีเกิดขึ้นที่นี่ โอกาสที่ดีในการใช้นิพจน์ทั่วไปที่เรียบง่าย

เวอร์ชันแรกล้มเหลวสำหรับสตริงที่มีอักขระพิเศษที่ถูกตีความภายใน regex รุ่นที่สอง (โดยใช้ re.escape) ใช้งานได้กับทุกกรณีทดสอบ การแก้ไขนั้นมีค่า 11 ไบต์

เวอร์ชันที่สองไม่ได้กำหนดอักขระทดแทนตามลำดับตามที่กำหนดในข้อกำหนดคุณสมบัติของปัญหาและตามที่ระบุไว้โดย @CarlosAlejo ดังนั้นกลับไปที่กระดานวาดภาพ

รุ่นที่ถูกต้องกอล์ฟเพิ่มเติม

  • -6 ไบต์บันทึกโดยไม่พิมพ์เอาต์พุตบนสองบรรทัด
  • +3 ไบต์: การสลับไปใช้การแทนที่โค้ดผ่านสตริงเพื่อให้สามารถตอบสนองความท้าทายตามที่ระบุไว้
  • -4 ไบต์: เนื่องจากฉันไม่ได้โทรหา re.findall สองครั้งฉันไม่จำเป็นต้องเปลี่ยนชื่อ
  • -5 ไบต์: สลับจากลูปเป็นลูปในขณะที่
  • ขอขอบคุณ @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+จะเป็น regex ที่สั้นกว่าการใช้ คุณจะไม่ไปมากกว่า 26 อย่างไรก็ตามไม่มีเหตุผลที่จะตรวจสอบให้แน่ใจว่ามันเป็น 1-2 หลักโดยเฉพาะ นอกจากนี้การใช้re.escapeหมายความว่าสตริงพื้นฐานreplaceสิ้นสุดลงสั้นลงเล็กน้อย: 253 ไบต์
หมึกมูลค่า

0

Lua, 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

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 แค่เล่น ๆ.

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.