ランレングスエンコーディングでテキストを短くする


8

ランレングスエンコーディングを使用してテキストを短くする(または短くする)

入力:

heeeello
うーん

出力:

1h4e2l1o
1w4o1r1l1d
  • stdinから行を読み取ります。
  • stdoutに出力します。
  • Stderrはもちろん破棄されます。
  • 非表示のテストケースがあると仮定します(出力の埋め込みなし)
  • ASCIIとしての入出力
  • すべての言語が受け入れられます

3
すべてを無視する場合(たとえば、w4orld代わりに1w4o1r1l1d(数値をエスケープする必要がある場合、たとえば `f111-> f3 \ 1´))、(通常)かなり節約できます。しかし、それはこれのほぼ複製になります:codegolf.stackexchange.com/questions/6774
— primo

1
それは、私が投票として閉じるのに実行レングスエンコーディングに十分に近いためです。それは、新しい挑戦や興味のあるポイントを提供するつもりはありません。
— Peter Taylor

フィックスポイントを見つけた人のボーナスポイント。
— FUZxxl 2012

4
@FUZxxl 22は簡単なフィックスポイントです。
— Peter Taylor、

2
@PeterTaylorそして空でない唯一のもの。数字で始まる必要があります。11不可能です。22で終了するか、で始まらない別の固定小数点が続く必要があり2ます。333nnn連続する奇数のインデックスで同じ文字を見つけることができないため、これは不可能なパターンです。4444同じ理由で失敗します。
— Khuldraeseth na'Barya

回答:


2

Perl: 46 →36または27文字

perl -pe's|((.)\2*)|@x=split//,$1;@x.$x[0]|eg'

すべての@ardnewはtr///c、分割する代わりに、演算子を使用して一致した文字列の文字数を数えるという考えを思いついた。

perl -pe's|((.)\2*)|$1=~y///c.$2|eg'

Degolfed:

while(defined($_ = <>)) {
  $_ =~ s{((.)\2*)}           # match 1 or more consecutive identical non-newlines
         {
           ($1 =~ y///c )     # count the number of characters in $1
           .                  # and concatenate it
           $2                 # with the first matched character
         }eg;                 # execute substitution, match "global"
  print $_;                   # print the modified line
}

使用法:

$ perl -pe's|((.)\2*)|$1=~y///c.$2|eg' infile

またはSTDIN経由

$ perl -pe's|((.)\2*)|$1=~y///c.$2|eg'
heeeello

プリント

1h4e2l1o

あなたはあなたのキャラクター数を少し変えています-私はpオプションの1を含めて37キャラクターを数えます。
— Gareth、

を使用するとs|((.)\2*)|$1=~y///c.$2|eg、合計で27文字(@Garethと同じ文字カウントルールを使用)を使用して10文字を節約できます
— ardnew

1
-p外側の括弧を削除することにより、さらに25バイト(を含む)に短縮できます。オンラインでお試しください!
— Xcali

2

Stax、7 バイト

ûèB☼å°╤

実行してデバッグしますst staxlang.xyz!

解凍(8バイト)と説明:

m|RFNppz
m           For each line of input:
 |R           Run-length encode: "heeeello" -> [[104,1],[101,4],[108,2],[111,1]]
   F          For each pair:
    N           Uncons-left: [104,1] -> push [104]; push 1
     ppz        Pop and print. Pop and print. Push "".
              Implicit print (always an empty string) with a newline

5バイト、1行でのみ機能します。

∩l↨me
|RmEp]    Unpacked
|R        Run-length encode: "heeeello" -> [[104,1],[101,4],[108,2],[111,1]]
  m       Map block over input:
   E        Explode array: [104,1] -> push 104, push 1
    p       Pop and print with no newline
     ]      Make a one-element list: 104 -> [104] (which is "h")
            Implicit print with newline

staxlang.xyzで実行してデバッグしてください!

おそらく合法ではありません。このプログラムは、各ペアを独自の行に出力します。少し大ざっぱ。

その出力形式が違法な場合は、6バイトを指定します。

╡δôZ→╬
|RFEp]p    Unpacked
  F        For each item in array, execute block:
      p      Pop and print with no newline
             No implicit print in for-each block, so no extra newlines

staxlang.xyzで実行してデバッグしてください!

言語の作成者は再帰的に指摘します。uncons-right(N)は、Eとを]独自に処理するため、これをアンパックした6バイトに短縮できます。ただし、この短いプログラムは、パックしても短くならないことがよくあります。これは一例です。まだ6バイト:|RFNpp編集:主な回答を更新する必要がありました。このフォームは私が使用したものです。


1
やった。 |RFNpp指定された出力を6バイトでアンパックできますが、残念ながらパックされません。
— 再帰的

1
@KevinCruijssenうん。おっと。
— Khuldraeseth na'Barya




1

Python 3反復、115 99 97バイト

while 1:
 a=b='';k=0
 for c in input():e=a!=c;b+=(str(k)+a)*e;k+=1-k*e;a=c
 print(b[1:]+str(k)+a)

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

Pythonの3再帰、136の 130 129バイト

f=lambda r,c,s,k=1:s and(c==s[0]and f(r,c,s[1:],k+1)or f(r+str(k)+c,s[0],s[1:]))or r[1:]+str(k)+c
while 1:print(f('','',input()))

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

反復的なアプローチはかなり成功しているようですが、再帰的なバージョンには改善の余地がたくさんあります。


素敵なアプローチです!whileコードのループは、入力を示すためだけにあるようです。それがなくても、コードは有効です。その場合、ループはコードの一部である必要はなく、最初の例を85バイトに減らすことができます。オンラインでお試しください!
— Jitse

2番目の例は、次のように121バイトに減らすことができます。オンラインでお試しください!
— Jitse

そう、whileループは行単位の入力専用です。ただし、質問では1行だけでなくすべての行を読み取る必要があるため、ループの外部化は規則に反します。
— movatica

1

05AB1E、9 バイト

|εÅγs.ιJ,

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

または代わりに:

|εÅγøí˜J,

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

説明:

|          # Read all lines of input as list
 ε         # For-each over the lines:
  Åγ       #  Run-length encode, pushing the list of characters and lengths separately
    s      #  Swap so the characters at at the top and lengths below it
     .ι    #  Interleave the two lists
       J   #  Join the list of characters and lengths together to a single string
        ,  #  And output it with trailing newline

|εÅγ       # Same as above
    ø      #  Zip/transpose; creating pairs of [character, length]
     í     #  Reverse each pair to [length, character]
      ˜    #  Deep flatten the pairs to a single list
       J,  #  Join them together to a single string, and output it with trailing newline


0

バッシュ:104文字

while read s;do e=;while [[ $s ]];do c=${s:0:1};n=${s##+($c)};e+=$[${#s}-${#n}]$c;s=$n;done;echo $e;done

サンプルの実行:

bash-4.2$ while read s;do e=;while [[ $s ]];do c=${s:0:1};n=${s##+($c)};e+=$[${#s}-${#n}]$c;s=$n;done;echo $e;done <<END
heeeello
woooorld
END
1h4e2l1o
1w4o1r1l1d

0

Zsh、117

while read s;do n=1;for i in {1..$#s};do if [[ $s[i] != $s[i+1] ]];then echo -n $n$s[i];n=0;fi;((n++));done;echo;done

次のように実行します。

zsh script.zsh < infile

脱ゴルフ

while read s; do                      # while stdin has more
  n=1                                 # repeat counter
  for i in {1..$#s}; do               # for each character
    if [[ $s[i] != $s[i+1] ]]; then   # same as next one?
      echo -n $n$s[i]                 # print if no
      n=0
    fi
    ((n++))
  done
  echo                                # newline between words
done

それらの空白は必要ですか、それとも「if [」を「if [」などに短縮できますか?
— mroman 2012

[[構築物は、(のような独自のIT上のコマンドである[)、および他のコマンドから分離しなければなりません。[overの使用に関しては[[、引用符で囲む"必要があるため、4つ追加する必要があります。
— トール


0

バーレスク(17B)

{=[{J[-jL[Q}\m}WL

{=[{^^[~\/L[Sh}\m}WL

古い/代替およびより長いバージョン:

{= [{^^ L [Sh \ /-] Sh。+} m [\ [} WL
{= [{^^ L [Sh \ /-] [-。+} m [\ [} WL
{= [{^^ L [Sh \ /-〜。+} m [\ [} WL
{= [{^^ L [Sh \ /-]。+} \ m} WL
{= [{^^ L [Sh \ / [〜。+} \ m} WL
{= [{^^ L [Sh \ / [〜_ +} \ m} WL
{= [{^^ L [Sh \ / fc。+} \ m} WL
{= [{^^ L [Sh \ /-〜。+} \ m} WL
{= [{^^ L [Sh \ /-] \ /} \ m} WL




0

Python 3、84バイト

def f(s,c=1):i,*j=s;b=j[:1]==[i];print(end='%s%s'%(c,i)*(b^1));f(j,1+b*c)
f(input())

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

説明

文字列の最初の文字と2番目の文字が等しいかどうかを確認します。ある場合は、カウンターを1増やします。そうでない場合は、カウンターと最初の項目を印刷し、カウンターを1にリセットします。どちらの場合も、最初の文字を削除して関数を再帰的に呼び出します。

文字列の終わりに達したときにエラーを発生させます。


I / O制限なし、ただし最小バイト数:

Python 3.8(プレリリース)、70バイト

f=lambda s:'%s%s'%(len(s)-len(t:=s.lstrip(p:=s[0])),p)+f(t)if s else''

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

Python 3相当(77バイト)

説明

文字列の先頭からすべての繰り返し文字を取り除きます。次に、元の文字列とストリップされた文字列の長さの差(1.)を含む文字列を返します。(2.)元の文字列の最初の文字。(3.)ストリップされた文字列に適用された再帰関数の結果。空の文字列が検出されると、再帰が終了します。


0

[スカラ(シェル)]、150バイト

scala.io.Source.stdin.getLines.foreach(s=>println{val(x,y,z)=s.tail.foldLeft(("",s.head,1)){case((a,b,c),d)=>if(b==d)(a,b,c+1)else(a+c+b,d,1)};x+z+y})

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

ここで、純粋なラムダのゴルフを解除しました(103バイト):

  s => {
    val (x,y,z) = s.tail.foldLeft(("", s.head, 1)) {
      case ((a, b, c), d) =>
        if (b == d)
          (a, b, c + 1)
        else
          (a + c + b, d, 1)
    }
    x+z+y
  }

0

ジュリア1.1、94の 84 81バイト

foldl(((n,l),c)->(c==l||print(n,l);((c==l&&n)+1,c)),readline()*'\n',init=("",""))

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


これは80バイトです。私はそれはもっと短くなると思う
— H.PWiz

残念ながら、私にとってJulia 1.1ではコードが機能しませんでした。私はまだ最後のタプルを手動で印刷'\n' するreadline()代わりに追加を追加することにより81をなんとかして得ました
— Simeon Schaub


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.