Реалізуйте кодування bzip2 довжиною виконання


14

Фон

Після застосування BWT (як це спостерігається у Burrows, Wheeler і Back ) та MTF (як це видно в Переміщенні на друкований фронт ASCII ), компресор bzip2 застосовує досить унікальну форму кодування довжиною пробігу.

Визначення

Для цієї задачі визначаємо перетворення BRLE наступним чином:

З огляду на рядок введення s, який складається виключно з символів ASCII з кодовими точками між 0x20 та 0x7A, виконайте наступне:

  1. Замініть кожен пробіг рівних символів одним явищем символу та збережіть кількість повторень після першого.

  2. Кодуйте кількість повторень після першого появи символу , використовуючи біективну нумерацію основи-2 та символи {та} .

    Невід’ємне ціле число n кодується як рядок b k … b 0 таким, що n = 2 k i (b k ) +… + 2 0 i (b 0 ) , де i ( {) = 1 і i ( }) = 2 .

    Зауважте, що це представлення завжди унікальне. Наприклад, число 0 кодується як порожній рядок.

  3. Вставте рядок фігурних дужок, що кодує кількість повторень після одного появи відповідного символу.

Покроковий приклад

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{{{"

Завдання

Реалізуйте інволютивну програму або функцію, яка зчитує окремий рядок зі STDIN або як аргумент командного рядка або функції та друкує або повертає або BRLE, або його зворотну рядок введення.

Якщо на вводі немає фігурних дужок, застосуйте BRLE. Якщо вхід містить фігурні дужки, застосуйте його обернену.

Приклади

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

Додаткові правила

  • Ви не можете використовувати будь-які вбудовані модулі, які обчислюють BRLE або його обернену рядок.

  • Ви можете використовувати вбудовані модулі, які:

    • Обчисліть RLE або RLD рядка до тих пір, поки кількість повторень не буде збережено у біективної базі-2.

    • Виконайте перетворення будь-якого типу.

  • Ваш код може надрукувати наступний новий рядок, якщо ви виберете STDOUT для виводу.

  • Ваш код повинен працювати на будь-якому введенні 1000 або менше символів ASCII в діапазоні від 0x20 до 0x7A, а також фігурні дужки (0x7B і 0x7D).

  • Якщо вхід містить фігурні дужки, ви можете припустити, що це дійсний результат застосування BRLE до рядка.

  • Діють стандартні правила гольф-коду. Виграє найкоротше подання в байтах.


Чому вбудовані не дозволяються?
MilkyWay90

Відповіді:


4

CJam, 50 48 байт

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

Дякуємо Деннісу за збереження 2 байт.

Спробуйте в Інтернеті.

Пояснення

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.

3

Pyth, 48 50 байт

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

2 байти завдяки @Maltysen

Демонстрація. Тестовий джгут.

Пояснення:

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. 

замість "{}"вас можна використовувати `H, прив’язаний до CJam :)
Maltysen

@Jakube Вибачте за суміш
isaacg

2

OCaml, 252

t це функція, яка виконує перетворення.

#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

Спочатку я думав, що повинен перевірити наявність фігурних брекетів, але це виявилося непотрібним. Розшифровка очевидно не впливає на рядки, які вже декодуються, і частина кодування виявилася настільки ж нешкідливою для тих, що вже були закодовані.


the encoding part proved equally harmlessробить це? Кодування 4{{8{{{G{{{{W{{{{{ви не отримаєте 4{{8{}G{{{W{{}?
edc65

@ edc65 Ні, я отримую відповідь, вказану в прикладах. Як ви її тестуєте?
feersum

"4 {{8 {{{{{{{{W {{{{{" як вхід не є одним із прикладів. Ви пробували?
edc65

@ edc65 Це зворотний бік одного із прикладів, і я перевірив їх обома способами. Так, я спробував це як перед публікацією, так і після вашого коментаря.
feersum

ОК добре. Я вказав на процитоване речення, оскільки "прямолінійне" кодування (як моє) взагалі не було б нешкідливим для даного тестового випадку. Очевидно, що ваша частина кодування є більш розумною.
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>

Деякі пояснення

Число n до BB2, використовуючи 0 і 1:(n+1).toString(2).slice(1)

Рядок в BB2 до числа: to_number ("0b1" + рядок) - тобто додайте крайній лівий 1 двійковий розряд і перетворіть з двійкового (і зменшіться на 1, не потрібно в цьому конкретному екземплярі).

Регулярний вираз, щоб знайти будь-який символ, за яким слідує {або }:/[^{}][{}]+/g

Регулярний вираз для пошуку повторних символів: /(.)\1*/g

За допомогою цього регулярного параграфа в якості заміни, перший параметр - це "повторний" знак (зрештою повторити всього 1 раз), другий параметр - загальний повторний рядок, довжина якого - це число, яке мені потрібно кодувати в BB2, що вже збільшується на 1

... потім зберіть все разом ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.