bzip2의 런 렝스 인코딩 구현


14

배경

Bzip ( 버로우, 휠러 및 백에 표시 ) 및 MTF ( 인쇄 가능한 ASCII 프론트이동에 표시 )를 적용한 후 bzip2 압축기는 다소 독특한 형식의 런-렝스 인코딩을 적용합니다.

정의

이 과제를 위해 변환 BRLE을 다음과 같이 정의합니다.

입력 문자열을 감안할 다음을 수행 전적으로가 0x20 및 0x7A 사이의 코드 포인트와 ASCII 문자로 구성 :

  1. 동일한 각 문자 실행을 한 번의 문자 발생으로 바꾸고 첫 번째 이후의 반복 횟수를 저장하십시오.

  2. bijective base-2 numeration 및 기호 및을 사용하여 문자가 처음 발생한 후 반복 횟수를 인코딩하십시오 .{}

    음이 아닌 정수 N은 문자열로 인코딩되는 B 형 K 합 ... 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 또는 문자열의 역수를 계산 기본 제공 기능을 사용합니다.

  • 다음과 같은 내장 기능을 사용할 수 있습니다 .

    • 반복 횟수가 bijective base-2에 저장되지 않는 한 문자열의 RLE 또는 RLD를 계산합니다.

    • 모든 종류의 기본 변환을 수행하십시오.

  • 출력에 STDOUT을 선택하면 코드에 줄 바꿈 문자가 인쇄 될 수 있습니다.

  • 코드는 0x20에서 0x7A 범위의 중괄호 (0x7B 및 0x7D)와 함께 1000 개 이하의 ASCII 문자를 입력해야합니다.

  • 입력에 중괄호가 포함 된 경우 BRLE을 문자열에 적용한 결과라고 가정 할 수 있습니다.

  • 표준 코드 골프 규칙이 적용됩니다. 바이트 단위의 최단 제출이 이깁니다.


내장은 왜 허용되지 않습니까?
MilkyWay90 17

답변:


4

CJam, 50 48 바이트

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

2 바이트를 절약 해 준 Dennis에게 감사합니다.

온라인으로 사용해보십시오.

설명

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

@Maltysen 덕분에 2 바이트.

데모. 테스트 하네스.

설명:

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. 

대신 CJam과 연결된을 "{}"사용할 수 있습니다 `H:)
Maltysen

@Jakube 믹스 업에 대해 죄송합니다.
isaacg

2

오캄, 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 {{{G {{{{W {{{{{"은 입력 값이 아닙니다.) 해봤 어?
edc65

@ edc65 그것은 예제 중 하나의 반대이며 두 가지 방법으로 테스트했습니다. 예, 귀하의 의견을 게시하기 전과 후에 시도했습니다.
feersum

그래 좋아. 나는 인용 된 문장을 지적했다. "직접적인"인코딩 (내 것과 같은)은 주어진 테스트 케이스에서 전혀 해를 끼치 지 않을 것이다. 분명히 인코딩 부분은 더 영리하다.
edc65

1

자바 스크립트 ( 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>

일부 설명

번호 n0과 1을 사용하여 에서 BB2까지(n+1).toString(2).slice(1)

BB2의 문자열을 숫자로 : to_number ( "0b1"+ string)-가장 왼쪽에있는 2 진 숫자를 추가하고 2 진에서 변환합니다 (이 특정 인스턴스에서는 필요하지 않은 1).

정규 표현식은 다음에 모든 문자를 찾기 위해 {또는} :/[^{}][{}]+/g

반복되는 문자를 찾기위한 정규식 : /(.)\1*/g

그 정규 표현식을 대체 할 때 첫 번째 매개 변수는 "반복 된"문자 (결국 1 번 반복)이고 두 번째 매개 변수는 총 반복 문자열이며 길이는 BB2에서 인코딩 해야하는 숫자입니다 이미 1 씩 증가했습니다.

... 그리고 모두 함께 모아라 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.