Perluas string yang disandikan

18

Ada pengkodean dan decoding run run klasik.

input   output
a3b2c5  aaabbccccc

Dan itu cukup lurus ke depan dan dilakukan sebelumnya.

Tantangannya adalah untuk juga memperhitungkan perilaku non-standar ketika beberapa karakter mendahului panjang lari ( satu digit dari 0-9). Setiap karakter sebelum digit panjang run (digit terakhir sebelum non-digit atau akhir string) memiliki nilai yang diterapkan secara individual dan dicetak secara berurutan.

Beberapa input dan output tes termasuk beberapa kasus tepi:

input   output
ab3c5   aaabbbccccc
a0b3    bbb  
13b1    111b
a13b1   aaa111b
a123b1  aaa111222b
aa2a1b1 aaaaab
  • Urutan karakter ( [a-zA-Z0-9]+) harus diikuti oleh panjang lamanya ( [0-9])
  • Hanya input yang valid yang perlu dipertimbangkan ( ([a-zA-Z0-9]+[0-9])*)
    • ya, string kosong adalah input yang valid.
  • Input adalah melalui input standar, output melalui output standar

Ini adalah kode golf, jumlah byte menentukan pemenangnya.


sumber
@AlexA. Benar. Ada beberapa esolang yang saya senang lihat dari waktu ke waktu yang jika tidak, akan dihukum oleh jumlah byte. (Saya tentu terbuka untuk saran mengapa ini mungkin menjadi kesalahan untuk menghitung seperti itu)
4
@MichaelT Pemberian skor berdasarkan karakter sangat mendorong kompresi kode sumber ke dalam UTF32, yang memungkinkan pengodean hingga 4 byte per karakter, tetapi sepenuhnya tidak dapat dibaca.
isaacg
@isaacg fair 'nuff. Saya akan mengedit untuk mengubah ke byte. Saya akan merenungkan cara untuk mengekspresikan gaya sclipting agar dapat diterima untuk tantangan di masa depan.
Apakah kiriman kami seharusnya selesai tanpa kesalahan jika inputnya adalah string kosong? The konsensus pada meta adalah bahwa output ke stderr dapat diabaikan, tetapi karena Anda secara eksplisit disebutkan itu, saya harus bertanya.
Dennis
@Dennis string kosong sebagai input seharusnya, harus berhenti. Seharusnya tidak masuk ke loop tak terbatas atau mencetak teks lain ke output standar.

Jawaban:

3

Pip, 22 + 1 = 23 byte

Menggunakan -rbendera Perhatikan bahwa ini mengharuskan Anda untuk 1) memasukkan EOF setelah input (Ctrl-D di Linux, Ctrl-Z di Windows) atau 2) menyalurkan input dari tempat lain.

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

Penjelasan:

                        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)

Hasil operasi peta sebenarnya adalah daftar daftar, tetapi secara default daftar hanya disatukan ketika dicetak, jadi tidak perlu konversi manual ke string.

Contoh, dengan input a13b1:

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

Pip memiliki dukungan regex dasar pada ... 2 hari yang lalu . Waktu yang tepat!

DLosc
sumber
Yang satu berfungsi (dan begitu juga master) dengan -rbendera. (Pertanyaan menentukan bahwa input harus berasal dari STDIN.)
Dennis
@ Dennis Ups, melewatkan itu. Menambahkan flag ke byte byte. Seharusnya saya bisa menggunakan variabel khusus qalih-alih atanpa tanda tambahan, tapi sepertinya ada bug dan meminta input dua kali.
DLosc
Akhirnya bahasa golf dengan dukungan regex!
Dennis
@ Dennis, saya melihat Anda bergeser ke pip sekarang!
Pengoptimal
8

Perl / Bash 54 40 + 1 = 41 byte

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

Ini pada dasarnya adalah sebuah regex di dalam sebuah regex. Dan sedikit keajaiban.

Penjelasan

Regex luar /(\D*\d*)(\d)/gmengekstrak setiap grup yang dikodekan run-length. Kami menangkap hal-hal untuk diulangi $1dan jumlah pengulangan di $2. Sekarang kami mengganti setiap kelompok tersebut dengan perluasan kelompok itu. Untuk itu, kami mengevaluasi kode "\$1=~s/./\$&x$2/egr" dua kali (seperti dengan /eebendera pada substitusi luar).

Evaluasi pertama hanya akan menginterpolasi jumlah pengulangan ke dalam string - variabel lainnya dilindungi oleh backslash. Jadi dengan asumsi input a14, kita sekarang akan memiliki kode $1=~s/./$&x4/egr, yang akan dievaluasi lagi.

Ini akan menerapkan substitusi ke konten $1(hal yang diulang a1). Substitusi cocok dengan setiap karakter .. The $&variabel memegang seluruh pertandingan, yang kita ulangi x4kali. Kami melakukan ini secara /global untuk setiap pertandingan dan /rmembuat string yang diganti daripada memodifikasi $1variabel (yang hanya baca). Jadi hasil dari substitusi batin adalah aaaa1111.

The -pbendera berlaku substitusi untuk setiap baris input dan mencetak hasilnya.

amon
sumber
3
Merupakan kebiasaan untuk menilai ini sebagai solusi Perl, di mana Anda hanya menambahkan 1 byte untuk -ppengubah. Saya menghitung 45 byte. Selain itu, Anda harus dapat menggunakan \Dalih-alih [a-z], yang juga menghilangkan kebutuhan i.
Dennis
7

CJam, 33 31 27 byte

Ughh, kurangnya ekspresi reguler membuat ini cukup lama ...

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

Bagaimana itu bekerja

Kami mengulangi semua karakter dari string input dan di setiap iterasi, melacak karakter yang terakhir ditemui (dimulai dengan karakter kosong untuk pertama kalinya). Kemudian kami memeriksa apakah karakter saat ini adalah non-numerik dan karakter terakhir adalah numerik. Jika demikian, kami mengulangi setiap karakter sebelumnya (yang belum pernah diulang), jumlah kali.

(Perluasan kode yang agak ketinggalan zaman)

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

Cobalah online di sini

Pengoptimal
sumber
Saya menghargai demonstrasi masalah yang menyebabkan kualifikasi byte. Terima kasih. Saya berpikir sedikit tentang bagaimana menyusun kualifikasi sedemikian rupa sehingga bahasa di mana instruksi tunggal adalah karakter multi-byte tidak dihukum untuk gaya bahasa itu tanpa mengizinkan pengkodean UTF yang Anda tunjukkan masuk melalui celah. PS Saya sangat suka melihat rincian algoritmik yang Anda berikan.
6

rs , 43 71 karakter

Yah, ini berubah dengan cepat. Angka bodoh ...

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

Coba di sini!

Versi asli (tidak berfungsi dengan input seperti 123):

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

Penjelasan

Baris pertama menempatkan spasi di antara run yang berisi angka, misalnya berubah a313menjadi a3 13.

Baris kedua terus memperluas pengkodean terkompresi seperti aa5ke a5a5.

Baris ketiga mengubah setiap instance a5menjadi aaaaamenggunakan operator pengulangan .

Baris terakhir menghilangkan spasi.

kirbyfan64sos
sumber
Bagaimana cara kerjanya a123b1?
Pengoptimal
@Optimizer Tidak baik. Saya perlu mengubah sedikit ...
kirbyfan64sos
@Optimizer Tetap.
kirbyfan64sos
5

Javascript ( ES6 ), 86 83 byte

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

Berkomentar:

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
            )
    )
)
nderscore
sumber
Tidak akan alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(c+1).join(b)))melakukan hal yang sama Panjangnya hanya 71 byte.
Ismael Miguel
@IsmaelMiguel yang hanya akan berfungsi jika ada karakter tunggal sebelum digit. Pemahaman array menangani pengulangan setiap karakter secara individual.
nderscore
Coba Array(6).join('12')dan itu akan kembali '1212121212'.
Ismael Miguel
Yang ini bekerja: alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(-~c).join(b)))(panjangnya sama 71 byte, diuji pada es6fiddle.net/ia7gocwg )
Ismael Miguel
1
Saya menemukan cara (jelas) yang berbeda untuk mengatakan 3 byte: D
nderscore
4

CJam, 27 25 byte

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

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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.
Dennis
sumber
3

Pyth, 33 32 28 byte

ssmm*vedkPdPcz-hMJf<@zT\=UzJ

Cobalah secara online: Demonstrasi atau Uji harness

Penjelasan

Saya akan menjelaskan kode menggunakan contoh input aa1a23b2. Semoga ini sedikit lebih mudah diikuti daripada tanpa.

                               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'
Jakube
sumber
2

Ruby 73

gets.split(/(\d)(?!\d)/).each_slice(2){|s,i|s.chars.map{|c|$><<c*i.to_i}}

Pengujian: http://ideone.com/L1fssb

Cristian Lupascu
sumber
2

JavaScript 112

alert(prompt().replace(/.*?\d+/g,function(m){for(i=n=m.length-1,o="";i--;){j=m[n];while(j--)o=m[i]+o}return o}))

wolfhammer
sumber
2

Python 2.7, 98 byte

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

Ini hanya melakukan pencarian regex sederhana untuk digit yang tidak diikuti oleh digit, dan kemudian melakukan string aritmatika pada setiap grup dan menggabungkan mereka semua kembali bersama.

rekursif
sumber
Anda dapat menyimpan 2 byte dengan beralih dari Python 2 ke 3. raw_inputmenjadi inputtetapi printmembutuhkan tanda kurung.
Alex A.
Benar, tapi saya lebih suka golf di python 2.7.
rekursif
1

Julia, 105 99 95 87 byte

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

Ini menciptakan fungsi tanpa nama yang mengambil string saat input a mengembalikan string. Untuk menyebutnya, berikan nama, misf=s->... .

Dua pemahaman array digunakan di sini, satu bersarang di dalam yang lain. Pemahaman luar bekerja pada setiap kecocokan string input terhadap ekspresi reguler \D*\d*\d. Pemahaman bagian dalam mengulangi setiap karakter pertandingan sesuai dengan digit yang tertinggal. Elemen-elemen dari array dalam digabungkan menjadi sebuah string, jadi array luar adalah sebuah array string. Ini bergabung dan dikembalikan.

Di Julia, string dapat diperlakukan seperti array karakter. Namun, perhatikan bahwa Chardan Stringtipe dalam Julia tidak memiliki metode yang sama didefinisikan; khususnya, tidak ada metode untuk pengulangan menggunakan ^untuk karakter. Ini menggunakan solusi yang berbelit-belit:

  • Ulangi string yang menghilangkan karakter terakhir, yang dihapus menggunakan chop().
  • Konversi karakter saat ini menjadi string menggunakan string().
  • Ubah digit trailing, yang juga merupakan karakter, menjadi bilangan bulat. Namun, perhatikan bahwa, misalnya,int('4') tidak mengembalikan 4. Sebaliknya, ia mengembalikan codepoint, yang dalam hal ini adalah 52. Dengan demikian kita dapat mengurangi 48 untuk mendapatkan kembali integer yang sebenarnya.
  • Ulangi string(b)sesuai denganint(p[end]) - 48 .

Contoh:

julia> f("ab3c5")
"aaabbbccccc"

julia> f("a0b3")
"bbb"

julia> f("13b1")
"111b"
Alex A.
sumber
1

Python 3, 148 144 136 135 Bytes

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)

Terima kasih kepada Pietu1998 dan mbomb007 untuk sarannya.

Python 2, 161 151 147 139 138 Bytes

Mungkin hari ini hanya merupakan hari yang panjang di tempat kerja, tetapi saya tidak bisa seumur hidup mencari tahu cara bermain golf ini ..

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
Kade
sumber
3
Mengubah ke Python 3 menyimpan beberapa byte ( raw_keluar, tanda kurung ke print). len(d)>0dapat diganti dengan dkarena daftar kosong adalah palsu dan daftar kosong tidak benar. list(...)dapat langsung menuju for. Kurung dalam w([...])tidak perlu karena itu satu-satunya argumen. Anda dapat menghapus ruang di ) for. Itu semua hal kecil yang saya buat sejauh ini.
PurkkaKoodari
@ Pietu1998 Terima kasih atas bantuannya!
Kade
Tanpa mengubah pendekatan Anda terlalu banyak, Anda dapat menyingkirkannya list()karena string dapat diubah. Anda bisa menggunakannya w=r=''. Jika Anda sering mengubahnya, lihat solusi saya. :)
rekursif
if c.isdigit()bisa menjadi if'/'<c<':', jika saya tidak salah.
DLosc
@Dosc, terima kasih, sepertinya berhasil.
Kade
0

Java 7, 175 byte

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;}

Tantangannya lebih sulit daripada yang terlihat, imo ..

Tidak digabungkan & kode uji:

Coba di sini.

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"));
  }
}

Keluaran:

aaabbbccccc
bbb
111b
aaa111b
aaa111222b
aaaaab
111222
Kevin Cruijssen
sumber