Terapkan pengkodean bzip2 run-length

14

Latar Belakang

Setelah menerapkan BWT (seperti yang terlihat di Burrows, Wheeler dan Kembali ) dan MTF (seperti yang terlihat di Pindahkan ke depan ASCII yang dapat dicetak ), kompresor bzip2 menerapkan bentuk pengodean run-length yang agak unik.

Definisi

Untuk tujuan tantangan ini, kami mendefinisikan transformasi BRLE sebagai berikut:

Diberikan string input s yang hanya terdiri dari karakter ASCII dengan titik kode antara 0x20 dan 0x7A, lakukan hal berikut:

  1. Ganti setiap run karakter yang sama dengan kemunculan tunggal karakter dan simpan jumlah pengulangan setelah yang pertama.

  2. Menyandikan jumlah pengulangan setelah kemunculan karakter yang pertama , menggunakan bijective base-2 numeration dan simbol {and }.

    Sebuah bilangan bulat non-negatif n dikodekan sebagai string b k ... b 0 sehingga n = 2 k i (b k ) + ... + 2 0 i (b 0 ) , di mana i ( {) = 1 dan i ( }) = 2 .

    Perhatikan bahwa representasi ini selalu unik. Misalnya, angka 0 dikodekan sebagai string kosong.

  3. Masukkan string kurung keriting yang mengkodekan jumlah pengulangan setelah kemunculan tunggal karakter yang sesuai.

Contoh langkah demi langkah

Input:  "abbcccddddeeeeeffffffggggggghhhhhhhh"
Step 1: "abcdefgh" with repetitions 0, 1, 2, 3, 4, 5, 6, 7
Step 2: "" "{" "}" "{{" "{}" "}{" "}}" "{{{"
Step 3: "ab{c}d{{e{}f}{g}}h{{{"

Tugas

Menerapkan program atau fungsi yang tidak sadar yang membaca string tunggal dari STDIN atau sebagai baris perintah atau argumen fungsi dan mencetak atau mengembalikan BRLE atau kebalikan dari string input.

Jika input tidak mengandung kurung keriting, terapkan BRLE. Jika input berisi kurung keriting, terapkan kebalikannya.

Contohnya

INPUT:  CODEGOLF
OUTPUT: CODEGOLF

INPUT:  PROGRAMMING
OUTPUT: PROGRAM{ING

INPUT:  PUZ{LES
OUTPUT: PUZZLES

INPUT:  444488888888GGGGGGGGGGGGGGGGWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
OUTPUT: 4{{8{{{G{{{{W{{{{{

INPUT:  y}}}{{
OUTPUT: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

Aturan tambahan

  • Anda tidak dapat menggunakan bawaan apa pun yang menghitung BRLE atau kebalikan dari string.

  • Anda dapat menggunakan bawaan yang:

    • Hitung RLE atau RLD dari suatu string, selama jumlah repetisi tidak disimpan dalam bijective base-2.

    • Lakukan konversi basis apa pun.

  • Kode Anda dapat mencetak baris tambahan jika Anda memilih STDOUT untuk hasil.

  • Kode Anda harus berfungsi untuk input 1000 atau kurang karakter ASCII dalam rentang dari 0x20 hingga 0x7A, ditambah kurung keriting (0x7B dan 0x7D).

  • Jika input berisi kurung keriting, Anda dapat mengasumsikan bahwa itu adalah hasil valid dari menerapkan BRLE ke string.

  • Aturan golf kode standar berlaku. Pengajuan terpendek dalam byte menang.

Dennis
sumber
Mengapa bawaan tidak diizinkan?
MilkyWay90

Jawaban:

4

CJam, 50 48 byte

l_{}`:T&1${_T#)_(@a?)+}%{(\2b)*}%@e`{(2b1>Tf=}%?

Terima kasih untuk Dennis karena telah menghemat 2 byte.

Cobalah online.

Penjelasan

l_              e# Read and duplicate input.
{}`:T           e# T = "{}"
&               e# If the input has '{ or '}:
    1$          e# Input.
    {           e# For each character:
        _T#)    e# If it is '{ or '}:
            _(  e# Return 0 for '{ or 1 for '}.
            @a  e# Otherwise, convert the character itself to an array (string).
        ?
        )+      e# If it is a number, increment and append to the previous array.
                e# If it is a string with at least 1 character, do nothing.
    }%
    {(\         e# For each character and bijective base 2 number:
        2b)*    e# Repeat the character 1 + that many times.
    }%
                e# Else:
    @           e# Input.
    e`          e# Run-length encoding.
    {(          e# For each character and length:
        2b1>    e# Convert the length to base 2 and remove the first bit.
        Tf=     e# Map 0 to '{ and 1 to '}.
    }%
?               e# End if.
jimmy23013
sumber
3

Pyth, 48 50 byte

J`Hs?m*hdi+1xLJtd2tczf-@zTJUz@Jzsm+ed@LJtjhd2rz8

2 byte berkat @Maltysen.

Demonstrasi. Uji harness.

Penjelasan:

J`Hs?m*hdi+1xLJtd2tczf-@zTJUz@Jzsm+ed@LJtjhd2rz8
                                                    Implicit: z = input()
                                                    H is empty dict.
J`H                                                 J = repr(H) = "{}"
   s                                                Print the concatenation of
    ?                        @Jz                    If z and J share any chars:
                     f     Uz                       Filter range(len(z))
                      -@zTJ                         On the absence of z[T] in J.
                   cz                               Chop z at these indices.
                                                    just before each non '{}'.
                  t                                 Remove empty initial piece.
     m*hd                                           Map to d[0] *
         i       2                                  the base 2 number                             
            xLJtd                                   index in J mapped over d[:-1]
          +1                                        with a 1 prepended.
                                             rz8    Otherwise, run len. encode z
                                 m                  map over (len, char)
                                         jhd2       Convert len to binary.
                                        t           Remove leading 1  
                                     @LJ            Map to element of J.
                                  +ed               Prepend char.
                                s                   Concatenate. 
isaacg
sumber
alih-alih "{}"yang bisa Anda gunakan `H, ikat dengan CJam :)
Maltysen
@ Jakube Maaf untuk mixup.
isaacg
2

OCaml, 252

t adalah fungsi yang melakukan transformasi.

#load"str.cma"open Str
let rec(!)=group_beginning and
g=function|1->""|x->(g(x/2)^[|"{";"}"|].(x mod 2))and($)i s=if g i=s then i else(i+1)$s and
t s=global_substitute(regexp"\(.\)\1*\([{}]*\)")(fun s->String.make(1$matched_group 2 s)s.[!1]^g(!2- !1))s

Awalnya saya berpikir saya harus memeriksa keberadaan kurung kurawal, tetapi ternyata tidak perlu. Dekoding jelas tidak berpengaruh pada string yang sudah diterjemahkan, dan bagian pengkodean terbukti sama-sama tidak berbahaya bagi string yang sudah dikodekan.

feersum
sumber
the encoding part proved equally harmlessmelakukannya? Pengkodean 4{{8{{{G{{{{W{{{{{tidak Anda dapatkan 4{{8{}G{{{W{{}?
edc65
@ edc65 Tidak, saya mendapatkan jawaban yang ditentukan dalam contoh. Bagaimana Anda mengujinya?
feersum
"4 {{8 {{G {{{{W {{{{{" sebagai input bukan salah satu contoh. Apakah kamu sudah mencobanya?
edc65
@ edc65 Ini adalah kebalikan dari salah satu contoh dan saya menguji keduanya. Ya, saya sudah mencobanya, baik sebelum memposting maupun setelah komentar Anda.
feersum
Oke bagus. Saya tunjukkan kalimat yang dikutip, sebagai "penyandian langsung (seperti milik saya) tidak akan berbahaya sama sekali dengan test case yang diberikan. Jelas bagian penyandian Anda lebih pintar.
edc65
1

JavaScript ( ES6 ), 162

f=s=>
(t=s[R='replace'](/[^{}][{}]+/g,n=>n[0].repeat('0b'+n[R](/./g,c=>c!='{'|0))))==s
?s[R](/(.)\1*/g,(r,c)=>c+r.length.toString(2).slice(1)[R](/./g,c=>'{}'[c])):t

// TEST
out=x=>O.innerHTML += x + '\n';

test=s=>O.innerHTML = s+' -> '+f(s) +'\n\n' + O.innerHTML;

[['CODEGOLF','CODEGOLF']
,['PROGRAMMING','PROGRAM{ING']
,['PUZ{LES','PUZZLES']
,['444488888888GGGGGGGGGGGGGGGGWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW','4{{8{{{G{{{{W{{{{{']
,['y}}}{{','yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy']]
.forEach(v=>{
  w=f(v[0])  
  out('Test ' + (w==v[1]?'OK':'Fail')+'\nInput:    '+v[0]+'\nExpected: '+v[1]+'\nResult:   '+w)
})  
Your test: <input id=I style='width:300px'><button onclick='test(I.value)'>-></button>
<pre id=O></pre>

Beberapa penjelasan

Nomor n ke BB2 menggunakan 0 dan 1:(n+1).toString(2).slice(1)

String dalam BB2 ke nomor: to_number ("0b1" + string) - yaitu, tambahkan 1 digit biner paling kiri dan konversikan dari biner (dan kurangi dengan 1, tidak diperlukan dalam contoh khusus ini).

Ekspresi reguler untuk menemukan karakter apa pun yang diikuti oleh {atau }:/[^{}][{}]+/g

Ekspresi reguler untuk menemukan karakter yang diulang: /(.)\1*/g

Menggunakan regexp di ganti, param pertama adalah char "repeat" (akhirnya hanya mengulang 1 kali), param kedua adalah total string yang diulang, yang panjangnya adalah angka yang harus saya encode dalam BB2 sudah bertambah 1

... lalu letakkan semuanya ...

edc65
sumber