RLEデータを圧縮してASCIIアートを描画する


11

この質問は、私が別の質問に答えるために思いついたものに基づいてます。

時々、ここの質問はいくつかのASCIIアートを描くように求めます。アートのデータを保存する簡単な方法の1つは、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回以上出現するグループを、文字列の順序または出現順に小文字の文字セットで置き換えますが、バッファーに格納します置換(置換ごとに "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データを含む文字列が与えられた場合、記述されているようにそれを圧縮するためにできる限り短いプログラム/関数/メソッドを記述します。アルゴリズムは2つの文字列を出力/返す必要があります。最初の文字列は圧縮に使用される辞書を含み、2番目の文字列は結果の圧縮文字列です。文字列は、タプル、配列、リストなど、指定した順序で返すことができます。

手順2で文字列を圧縮できない場合、アルゴリズムは最初の戻り値として空の文字列を返し、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回以上繰り返されることは決してないからですaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Okx

@Okxそんなことはありえません。
Erik the Outgolfer 2017年

@Okxはい、現実の世界では。ただし、ルールは制限されたASCIIアートのセットで構成されています。
チャーリー

2
実際の実装でS,aT bK@cは、S,T K@そこから簡単に推定できる置換文字に明示的に名前を付けずに、おそらく格納されます。
Arnauld 2017年

@Arnauldあなたは完全に正しいです、私はそれを逃しましたが、誰かが彼/彼女の答えを書き始めた場合に備えて、私は質問をそのままにします。
チャーリー

回答:


3

JavaScriptの(ES6)、168の 167バイト

2つの文字列の配列を返します:[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

パイソン2269の 280 268 266バイト

ここで空想は何も起こっていません。いくつかの単純な正規表現を使用する良い機会です。

正規表現内で解釈される特殊文字を含む文字列の最初のバージョンは失敗しました。2番目のバージョン(re.escapeを使用)は、すべてのテストケースで動作します。この修正には11バイトかかります。

2番目のバージョンは、問題の仕様で要求されているように、@ CarlosAlejoによって指摘されているように、置換文字を順番に割り当てていませんでした。それで、設計図に戻ります。

修正版、さらにゴルフ

  • 出力を2行に出力しないことで節約される-6バイト
  • +3バイト:文字列を使用してコード置換に切り替え、指定されたとおりにチャレンジに対応できるようにします。
  • -4バイト:re.findallを2回呼び出す必要がなくなったので、名前を変更する必要はありません。
  • -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

オンラインでお試しください!


もう少しで完了です。2番目のステップのグループが適切な順序で作成されていないことに注意してください(例を参照)。グループは出現順に作成する必要があるため、最初のグループはにする必要がありますO,a
チャーリー

@CarlosAlejo機能的な観点から、置換は任意であるため、要件としてこれを指摘していませんでした。Pythonのデフォルトの辞書は、これを実装する自然な方法であり、順不同です。他の可能なデータ構造を検討する必要があります....
CCB60

b=a=input()and を使用していくつかのバイトを節約できませんでしたn,s,p=96,'',0か?
同志SparklePony 2017年

\d+使用する正規表現は短くなります。とにかく26を超えることは決してないので、具体的には1〜2桁であることを確認する理由はありません。また、使用re.escapeすると、基本的な文字列replaceがわずかに短くなることを意味します
Value Ink

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の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.