エンコードされた文字列を展開する


18

古典的なランレングスのエンコードとデコードがあります。

input   output
a3b2c5  aaabbccccc

そして、それはかなり簡単で前に行われました。

課題は、複数の文字がランレングス(0〜9の1桁)に先行する場合の非標準的な動作も考慮することです。ランレングス数字の前の各文字(数字以外または文字列の最後の前の最後の数字)には、その値が個別に適用され、順番に出力されます。

いくつかのエッジケースを含むいくつかのテスト入力および出力:

input   output
ab3c5   aaabbbccccc
a0b3    bbb  
13b1    111b
a13b1   aaa111b
a123b1  aaa111222b
aa2a1b1 aaaaab
  • 文字シーケンス([a-zA-Z0-9]+)の後には、ランレングス長([0-9])が続く必要があります
  • 有効な入力のみを考慮する必要があります(([a-zA-Z0-9]+[0-9])*
    • はい、空の文字列は有効な入力です。
  • 入力は標準入力経由、出力は標準出力経由

これはコードゴルフで、バイト数が勝者を決定します。


@AlexA。正しい。私は時々バイトカウントによってペナルティを受けるいくつかのエソランがあります。(私はこれがそのように数えるのが間違いかもしれない理由についての提案に確かにオープンです)

4
@MichaelT文字によるスコアリングは、ソースコードをUTF32に圧縮することを強く推奨します。これにより、文字ごとに最大4バイトのエンコードが可能になりますが、完全には判読できません。
isaacg

@isaacg fair 'nuff。編集してバイトに変更します。スクリプティングのスタイルを将来の課題に受け入れられるように表現する方法について反論します。

入力が空の文字列である場合、送信はエラーなしで完了するはずですか?メタ上のコンセンサスが STDERRに出力を無視することができるということですが、明示的に言及しているので、私は聞いています。
デニス

@Dennis入力として空の文字列を停止する必要があります。無限ループに入ったり、他のテキストを標準出力に出力したりしないでください。

回答:


3

ピップ、22 + 1 = 23バイト

-rフラグを使用します。これには、1)入力後にEOFを入力する(LinuxではCtrl-D、WindowsではCtrl-Z)か、2)別の場所から入力をパイプする必要があることに注意してください。

(^_@<v)X_@vMa@`\D*\d+`

説明:

                        a is first line of stdin (from -r flag) and v is -1 (implicit)
              `\D*\d+`  Pattern (regex) object that matches zero or more non-digits
                        followed by at least one digit
            a@          Find all non-overlapping matches in a, returning a list of strings
           M            To that list, map a lambda function:
  _@<v                    Argument sans last character (equivalent to Python a[:-1])
(^    )                   Split into a list of characters
        _@v               Last character of argument
       X                  Repeat each character of the list that many times
                          (String multiplication X, like most operators, works item-wise
                          on lists)
                        Auto-print (implicit)

マップ操作の結果は実際にはリストのリストですが、デフォルトではリストは印刷時に単純に連結されるため、文字列への手動変換は不要です。

例、入力ありa13b1

Var a gets        "a13b1"
After regex match  ["a13" "b1"]
After map          [["aaa" "111"] ["b"]]
Final output       aaa111b

Pipは2日前の時点で基本的な正規表現をサポートしています。素晴らしいタイミング!


それは-rフラグで動作します(そしてマスターも動作します)。(質問は、入力がSTDINからのものでなければならないことを指定しています。)
デニス

@デニスおっと、それを見逃した。バイトカウントにフラグを追加しました。追加のフラグなしqで特殊変数を使用できるはずaでしたが、バグがあるようで、入力を2回要求しています。
DLosc

最後に正規表現をサポートしたゴルフ言語!
デニス

@デニス今、あなたはピップにシフトしているのを見ます!
オプティマイザー

8

Perl / Bash 54 40 + 1 = 41バイト

perl -pe's:(\D*\d*)(\d):"\$1=~s/./\$&x$2/egr":ege'

基本的に、正規表現内の正規表現です。そしてちょっとした魔法。

説明

外側の正規表現は、/(\D*\d*)(\d)/g各ランレングスでエンコードされたグループを抽出します。で繰り返すものと繰り返し$1数をキャプチャし$2ます。次に、そのような各グループをそのグループの展開で置き換えます。そのために、コードを"\$1=~s/./\$&x$2/egr" 2回評価します(/ee外部置換のフラグによる)。

最初の評価では、繰り返し回数が文字列に補間されるだけです。他の変数はバックスラッシュで保護されます。したがって、入力を仮定するa14と、コードが得られ$1=~s/./$&x4/egr、再び評価されます。

これにより、置換が$1(繰り返されるものa1)のコンテンツに適用されます。置換は各文字に一致します.$&変数は、私たちが繰り返して全試合、保持x4時間を。これを/g一致ごとにloballyで実行し/r$1変数(読み取り専用)を変更するのではなく、置換された文字列を返します。したがって、内部置換の結果はaaaa1111です。

この-pフラグは、各入力行に置換を適用し、結果を出力します。


3
これをPerlソリューションとしてスコアリングするのが慣例であり、-p修飾子に1バイトを追加するだけです。45バイトをカウントします。さらに、の\D代わりにを使用できるはず[a-z]ですi。これにより、の必要性もなくなります。
デニス

7

CJam、33 31 27バイト

うーん、正規表現の欠如はこれをかなり長くします...

qN+{:XA,s&L\:L>{])~e*[}&X}%

使い方

入力文字列のすべての文字をループ処理し、各反復で、最後に検出された文字を追跡します(最初に空の文字から開始します)。次に、現在の文字が数字でないかどうかを確認しますはなく、最後の文字が数字であるます。その場合、前の各文字(まだ繰り返されていない)をnumber回繰り返します。

(少し時代遅れのコード拡張)

q{                       }%        e# Read the input (q) and loop through each character
  L                                e# Put variable L (initially empty character) on stack
   A,                              e# Put variable A (equals 10) and create an array 0..9
     s                             e# Convert the array to string "0123456789"
      &                            e# Do a set intersect b/w previous char and 0-9 string
                                   e# If numeric, it gives 1 char string, otherwise 0
       \:LA,s&                     e# Swap to bring current character on top. Store it in L
                                   e# and do the same set intersect with it
              >                    e# Means we are checking that current char is non-numeric
                                   e# and previous numeric
               {      }&           e# Run this block if above is true
                ])~                e# Wrap everything not already repeated in an array and
                                   e# take out the last character and convert it to integer.
                                   e# This is the run length of the preceding string
                   e*              e# Repeat each character in the string, run length times
                     [             e# Start a new array to help when next run length is found
                        L          e# Restore the current character back on stack to be used
                                   e# in next iteration
                           )~e*    e# The last string-run-length pair is not decoded..
                                   e# So we do that now

こちらからオンラインでお試しください


バイト修飾子が引き起こす問題のデモンストレーションに感謝します。ありがとうございました。単一の命令がマルチバイト文字である言語が、そのスタイルの言語に対して、あなたが示したUTFエンコーディングが抜け穴を介して入ることを許さずにペナルティを受けないように、資格を表現する方法について少し考えています。PSあなたが提供するアルゴリズムの内訳を見るのは本当に好きです。

6

rs43 71文字

さて、これはすぐに長くなりました。愚かな数字...

(\d)(\D)/\1 \2
+(\w)(\w+?)(\d)(?= |$)/\1\3 \2\3
(\w)(\d)/(\1)^^(\2)
 /

ここで試してみてください!

元のバージョン(などの入力では機能しませんでした123):

+(\D)(\D+)(\d)/\1\3\2\3
(\D)(\d)/(\1)^^(\2)

説明

最初の行は、例えば、数字を含む回すの実行の間にスペース置きa313にしますa3 13

2行目は、次のような圧縮されたエンコーディングを連続的に展開します aa5a5a5ます。

3行目は、繰り返し演算子a5aaaaa使用してのすべてのインスタンスをに変換します

最後の行はスペースを削除します。


どのように処理しa123b1ますか?
オプティマイザー

@Optimizerよくない。少し調整する必要があります
...-kirbyfan64sos

@Optimizerが修正されました。
kirbyfan64sos

5

Javascript(ES6)、86 83バイト

alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>b.replace(/./g,y=>y.repeat(c))))

コメント:

alert( // output final result
    prompt(). // take input
    replace(/(.+?)(\d)(?!\d)/g, // replace ungreedy capture group of any characters 
                                // followed by a digit (captured)
                                // and not followed by a digit (negative lookahead)
        (a, b, c)=> // replace with a function
            b.replace(/./g, // replace all characters in b
                y=>y.repeat(c) // with that character repeated c times
            )
    )
)

alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(c+1).join(b)))同じことをしませんか?長さはたった71バイトです。
イスマエルミゲル

@IsmaelMiguelは、数字の前に単一の文字がある場合にのみ機能します。配列内包表記では、各文字を個別に繰り返し処理します。
nderscore

試してみてくださいArray(6).join('12')、それが返されます'1212121212'
イスマエルミゲル

これは動作します:(alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(-~c).join(b)))同じ71バイトの長さ、es6fiddle.net / ia7gocwgでテスト)
イスマエルミゲル

1
しかし、3バイトと言う別の(明白な)方法を見つけました:D
nderscore

4

CJam、27 25バイト

r_'A+1>.{64&1$>{])~f*o}&}

CJamインタープリターでオンラインで試す

使い方

r_                        e# Read a token from STDIN and push a copy.
  'A+                     e# Append the character A to the copy.
     1>                   e# Discard the first character of the copy.
       .{               } e# For each character C of the input string and the
                          e# corresponding character D of the copy:
         64&              e#   Take the bitwise and of D and 64. This pushes @
                          e#   if D is a letter and NUL if it is a digit.
            1$>           e#   Compare the result to a copy of C. This pushes 1
                          e#   if and only if D is a letter and C is a digit.
               {      }&  e#   If the result was 1, do the following:
                ]         e#     Wrap the stack in an array.
                 )~       e#     Pop and evaluate the last character.
                   f*     e#     Repeat each char in the array that many times.
                     o    e#     Print all characters.

3

Pyth、33 32 28バイト

ssmm*vedkPdPcz-hMJf<@zT\=UzJ

オンラインで試す:デモンストレーションまたはテストハーネス

説明

入力例を使用してコードを説明しますaa1a23b2。うまくいけば、これはない場合よりも簡単に理解できます。

                               implicit: z = input string = 'aa1a23b2'
                         Uz    the indices of z: [0, 1, 2, 4, 5, 6, 7]
                  f            filter for indices T, which satisfy:
                   <@zT\=        z[T] < "="
                               this gives us the list of indices [2, 4, 5, 7], 
                               which correspond to digits in z. 
                 J             assignment, J = [2, 4, 5, 7]
               hMJ             increment all element in J: [3, 5, 6, 8]
              -            J   and remove the elements of J:
                                 [3, 5, 6, 8] - [2, 4, 5, 7] = [3, 6, 8]
            cz                 split z at these indices: ['aa1', 'a23', 'b2', '']
           P                   remove last element: ['aa1', 'a23', 'b2']
  m                            map each string d to:
   m     Pd                      map each string k of d-without-last-char to:
     ved                           int(last element of d)
    *   k                          * k
                               this creates [['a', 'a'], ['aaa', '222'], ['bb']]
 s                             sum the lists: ['a', 'a', 'aaa', '222', 'bb']
s                              sum the strings: 'aaaaa222bb'



2

Python 2.7、98バイト

import re
print"".join(c*int(m[-1])for m in 
re.findall(r".+?\d(?!\d)",raw_input())for c in m[:-1])

これは、数字が後に続かない数字の単純な正規表現検索を行い、各グループで文字列演算を行い、それらをすべて結合し直します。


Python 2から3に切り替えると2バイト節約できますraw_inputinputprint括弧が必要になります。
アレックスA.

確かに、Python 2.7でゴルフをすることを好みます。
再帰的

1

ジュリア、105 99 95 87バイト

s->join([join([string(b)^(int(p[end])-48)for b=chop(p)])for p=matchall(r"\D*\d*\d",s)])

これは、入力として文字列を受け取り、文字列を返す名前のない関数を作成します。呼び出すには、名前を付けf=s->...ます。

ここでは、2つの配列内包表記が使用され、一方が他方にネストされています。外部の内包表記は、正規表現に対する入力文字列の各一致に作用します\D*\d*\d。内包表記は、末尾の数字に従って一致の各文字を繰り返します。内部配列の要素は文字列に結合されるため、外部配列は文字列の配列になります。これらは結合されて返されます。

Juliaでは、文字列は文字配列のように扱うことができます。ただし、Julia のCharand String型には同じメソッドが定義されていないことに注意してください。特に、^for文字を使用して繰り返しを行う方法はありません。これは複雑な回避策を使用します。

  • 使用して削除される最後の文字を省略して、文字列をループします chop()
  • を使用して、現在の文字を文字列に変換しstring()ます。
  • 文字でもある末尾の数字を整数に変換します。ただし、たとえば、int('4')4は返されないことに注意してください。むしろ、この場合は52であるコードポイントを返します。したがって、48を減算して実際の整数を取得できます。
  • string(b)に従って繰り返しint(p[end]) - 48ます。

例:

julia> f("ab3c5")
"aaabbbccccc"

julia> f("a0b3")
"bbb"

julia> f("13b1")
"111b"

1

Python 3、148 144 136 135バイト

w,o,r,d=''.join,'',[],[]
for c in input()+' ':
 if'/'<c<':':d+=[c]
 elif d:o+=w(x*int(w(d))for x in r);r=[c];d=[]
 else:r+=[c]
print(o)

Pietu1998とmbomb007の提案に感謝します。

Python 2、161 151 147 139 138バイト

たぶん今日は仕事で長い一日だったかもしれませんが、私の人生ではこれをゴルフする方法を理解することはできません。

w,o,r,d=''.join,'',[],[]
for c in raw_input()+' ':
 if'/'<c<':':d+=[c]
 elif d:o+=w(x*int(w(d))for x in r);r=[c];d=[]
 else:r+=[c]
print o

3
Python 3に変更すると、数バイト(raw_out、括弧print)を節約できます。空のリストは偽であり、空ではないリストは真実であるため、len(d)>0で置き換えることができますdlist(...)に直接行くことができforます。角括弧w([...])は唯一の引数であるため不要です。でスペースを削除でき) forます。これが私がこれまでに思いついた些細なことのすべてです。
-PurkkaKoodari

@ Pietu1998助けてくれてありがとう!
ケード

アプローチをあまり変更しなくてもlist()、文字列は反復可能であるため削除できます。を使用できますw=r=''。大幅に変更する場合は、私の解決策をご覧ください。:)
再帰的

if c.isdigit()if'/'<c<':'私が間違っていなければ、になることができます。
DLosc

@DLoscありがとう、それはうまくいくようです。
ケード

0

Java 7、175バイト

String c(String s){String r="",a[];for(String x:s.split("(?<=(\\d)(?!\\d))")){a=x.split("");for(int i=0,j,l=a.length-1;i<l;i++)for(j=0;j++<new Short(a[l]);r+=a[i]);}return r;}

挑戦は見た目よりも難しいです。

未ゴルフ&テストコード:

ここで試してみてください。

class M{
  static String c(String s){
    String r = "",
           a[];
    for(String x : s.split("(?<=(\\d)(?!\\d))")){
      a = x.split("");
      for(int i = 0, j, l = a.length-1; i < l; i++){
        for(j = 0; j++ < new Short(a[l]); r += a[i]);
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c("ab3c5"));
    System.out.println(c("a0b3"));
    System.out.println(c("13b1"));
    System.out.println(c("a13b1"));
    System.out.println(c("a123b1"));
    System.out.println(c("aa2a1b1"));
    System.out.println(c("123"));
  }
}

出力:

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