Implementa la codifica run-length di bzip2


14

sfondo

Dopo aver applicato il BWT (come visto in Burrows, Wheeler e Back ) e l'MTF (come visto in Sposta sul fronte ASCII stampabile ), il compressore bzip2 applica una forma piuttosto unica di codifica di lunghezza di esecuzione.

Definizione

Ai fini di questa sfida, definiamo la trasformazione BRLE come segue:

Data una stringa di input s che si compone esclusivamente di caratteri ASCII con punti di codice tra 0x20 e 0x7A, effettuare le seguenti operazioni:

  1. Sostituisci ogni serie di caratteri uguali con una singola occorrenza del personaggio e memorizza il numero di ripetizioni dopo la prima.

  2. Codifica il numero di ripetizioni dopo la prima occorrenza del personaggio , usando la numerazione biiettiva base-2 e i simboli {e }.

    Un numero intero non negativo n è codificato come stringa b k … b 0 tale che n = 2 k i (b k ) +… + 2 0 i (b 0 ) , dove i ( {) = 1 e i ( }) = 2 .

    Nota che questa rappresentazione è sempre unica. Ad esempio, il numero 0 è codificato come una stringa vuota.

  3. Inserisci la stringa di parentesi graffe che codifica il numero di ripetizioni dopo la singola occorrenza del carattere corrispondente.

Esempio passo-passo

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

Compito

Implementare un programma o una funzione involutiva che legge una singola stringa da STDIN o come argomento della riga di comando o della funzione e stampa o restituisce BRLE o il suo inverso della stringa di input.

Se l'input non contiene parentesi graffe, applicare BRLE. Se l'input contiene parentesi graffe, applicare il suo inverso.

Esempi

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

Regole aggiuntive

  • Non è possibile utilizzare alcun built-in che calcola BRLE o il suo inverso di una stringa.

  • È possibile utilizzare built-in che:

    • Calcola RLE o RLD di una stringa, purché il numero di ripetizioni non sia memorizzato in bijective base-2.

    • Esegui la conversione di base di qualsiasi tipo.

  • Il codice può stampare una riga finale se si sceglie STDOUT per l'output.

  • Il codice deve funzionare per qualsiasi input di 1000 o meno caratteri ASCII nell'intervallo da 0x20 a 0x7A, oltre alle parentesi graffe (0x7B e 0x7D).

  • Se l'input contiene parentesi graffe, si può presumere che sia un risultato valido dell'applicazione di BRLE a una stringa.

  • Si applicano le regole standard per il golf. Vince l'invio più breve in byte.


Perché i builtin non sono ammessi?
MilkyWay90

Risposte:


4

CJam, 50 48 byte

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

Grazie per Dennis per aver salvato 2 byte.

Provalo online.

Spiegazione

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 byte

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

2 byte grazie a @Maltysen.

Dimostrazione. Collaudare l'imbragatura.

Spiegazione:

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. 

invece di "{}"te puoi usare `H, legato con CJam :)
Maltysen il

@Jakube Ci scusiamo per il disguido.
Isaacg,

2

OCaml, 252

t è la funzione che esegue la trasformazione.

#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

All'inizio pensavo di dover verificare la presenza di parentesi graffe, ma si è rivelato superfluo. La decodifica chiaramente non ha alcun effetto sulle stringhe che sono già state decodificate e la parte di codifica si è dimostrata altrettanto innocua rispetto a quelle che erano già state codificate.


the encoding part proved equally harmlesslo fa? La codifica 4{{8{{{G{{{{W{{{{{non capisci 4{{8{}G{{{W{{}?
edc65,

@ edc65 No, ottengo la risposta specificata negli esempi. Come lo testate?
feersum,

"4 {{8 {{{G {{{{W {{{{{" come input non è uno degli esempi. L'hai provato?
edc65,

@ edc65 È l'inverso di uno degli esempi e li ho testati in entrambi i modi. Sì, l'ho provato, sia prima di pubblicare che dopo il tuo commento.
feersum,

Ok bene. Ho sottolineato la frase citata, poiché una codifica "semplice" (come la mia) non sarebbe affatto innocua con il caso di test dato. Chiaramente la tua parte di codifica è più intelligente.
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>

Qualche spiegazione

Numero n da BB2 usando 0 e 1:(n+1).toString(2).slice(1)

Stringa in BB2 al numero: to_number ("0b1" + stringa) - ovvero, aggiungi una cifra binaria 1 più a sinistra e converti da binario (e diminuisci di 1, non necessario in questa specifica istanza).

Espressione regolare per trovare qualsiasi carattere seguito da {o }:/[^{}][{}]+/g

Espressione regolare per trovare personaggi ripetuti: /(.)\1*/g

Usando quel regexp in sostituzione, il primo parametro è il carattere "ripetuto" (eventualmente ripeti solo 1 volta), il secondo parametro è la stringa ripetuta totale, la cui lunghezza è il numero che devo codificare in BB2 già incrementato di 1

... poi metti tutto insieme ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.