Encoder dinamico ASCII!


16

introduzione

Alcuni personaggi ASCII sono così costosi in questi giorni ...

Per risparmiare denaro hai deciso di scrivere un programma che codifica personaggi costosi usando quelli economici.

Tuttavia, i prezzi dei personaggi cambiano frequentemente e non vuoi modificare il tuo programma ogni volta che devi codificare o decodificare un personaggio diverso! Avrai bisogno di una soluzione più dinamica.

Sfida

Il tuo compito è scrivere due programmi: un codificatore e un decodificatore .

L' encoder dovrebbe accettare un elenco di cinque caratteri economici e un singolo carattere costoso.

Dovrebbe generare una singola stringa composta da caratteri economici, che codifica per il carattere costoso.

Questa stringa non può essere più lunga di 4 caratteri , per rimanere poco costosa. Tuttavia, non è necessario utilizzare tutti i caratteri economici nella codifica e le codifiche possono avere lunghezze diverse.


Il decodificatore dovrebbe accettare la stringa emessa dall'encoder e produrre il carattere costoso.

Il decodificatore non accetta input se non la stringa codificata. Deve funzionare, non modificato, dall'output dell'encoder per qualsiasi combinazione (valida) di input. In altre parole, il tuo programma di decodifica non sa quali caratteri sono costosi o poco costosi.

punteggio

Il codice combinato più breve vince!

Appunti

  • Tutti i caratteri saranno lettere maiuscole [A-Z], lettere minuscole [a-z]o numeri [0-9].

  • L'elenco dei personaggi economici non conterrà duplicati. Nessun personaggio sarà sia economico che costoso.

  • L'encoder e il decoder non devono essere scritti nella stessa lingua, ma possono esserlo. È possibile scrivere un programma o una funzione.

  • L'input e l'output possono essere in qualsiasi formato ragionevole per la tua lingua.

  • I due programmi non possono condividere variabili o dati.

Sommario

  • L'immissione di alcuni caratteri economici e un carattere costoso viene data all'encoder.

  • Encoder genera una stringa di caratteri economici, codificando il carattere costoso.

  • Al decodificatore viene fornita l'output dell'encoder e viene emesso il carattere costoso.

Esempi

Ingresso:     a, b, c, d, e     f

Possibilità dell'encoder:     a     eeee     caec

decoder:     f


Ingresso:     a, b, c, d, e     h

Possibilità dell'encoder:     bc     cea     eeaa

decoder:     h


Ingresso:     q, P, G, 7, C     f

Possibilità dell'encoder:     777     P7     PPCG

decoder:     f


Potrei davvero essere io, e mi scuso per questa domanda, se lo è, ma come dovresti codificare il tuo messaggio con i personaggi economici? Aggiunta dei codici ASCII per i 5 caratteri economici? In realtà, questa domanda ha una base solo se il decodificatore deve decodificare per tutte le possibilità di codifica generate.
Cole

Per essere chiari: le possibilità dell'encoder sono solo esempi e possiamo codificare ogni carattere come vogliamo, sì?
Dennis,

@Dennis Sì, quelli sono solo esempi.
jrich

@Cole Senza rivelare un vero algoritmo , poiché questa è la sfida principale qui, credo che sia possibile. Ci sono solo 62 possibili lettere costose da codificare, e con questi 4 caratteri ASCII è possibile codificare fino a 92, secondo A239914 . (enorme grazie al commento sandbox di PhiNotPi per questo - non ho calcolato esattamente quanti potrebbero essere codificati)
jrich

@UndefinedFunction Mi rendo conto ora di ciò che intendevi: la domanda di Dennis ha risposto a ciò di cui ero confuso.
Cole

Risposte:


5

Pyth, 46 byte

Encoder, 22 byte

@smfql{Td^<Szd4S4-Cw48

Decodificatore, 24 byte

C+48xsmfql{Td^<sS{zd4S4z

Caspita, si adatta perfettamente. 75 diverse combinazioni di caratteri e un range di caratteri di 75.
Jakube

Penso che puoi sostituire S4con Te salvare ogni byte in entrambi i programmi.
Jakube,

7

CJam, 55 50 48 47 byte

Encoder, 24 22 21 byte

l$:L4m*{$L|L=},rc'0-=

Provalo online.

Decodificatore, 31 28 27 26 byte

4_m*{$4,|4,=},l_$_|f#a#'0+

Provalo online.


Esiste un foglio di sintassi CJam là fuori che usi? Quello su sourceforge e quell'altro cheat sheet in pdf non contengono tutti i personaggi che usi come'
Luminous

'non è un operatore. Puoi trovarlo nella pagina della sintassi .
Dennis,

4

sbalorditivo, 163 + 165 = 328

Testato con gawk 4.1.1, ma dovrebbe funzionare anche nelle versioni precedenti di gawk. Deve essere leggermente modificato (allungato) per funzionare con il mawk.

encoder (163):

{for(gsub(", ",_);sprintf("%c",++r)!=$NF;asort(a))split($1,a,_);r-=r>64?53:46;for(k=4^5;r-=_~i;j=_)for(i=++k;gsub(++j,_,i);)split(k,b,_);for(j in b)printf a[b[j]]}

decodificatore (165):

{split($1,a,_);for(i in a)d[a[i]]=a[i];asort(d);for(k=4^5;c!~$1;x+=_~i){i=++k;for(c=j=_;gsub(++j,_,i);split(k,b,_));for(g in b)c=c d[b[g]]}printf"%c",x+(x>10?54:47)}

Bene, funziona, ma sono consapevole che questo potrebbe non essere l'approccio migliore per questo. Non ho idea di cosa serva la quinta lettera economica, perché ne uso solo quattro.

Questi sono esclusivamente monouso. Se si desidera inserire un secondo codice, è necessario riavviarli. Gli spazi dopo le virgole sono richiesti nell'input per codificare.

Cosa ho pensato

La mia prima domanda era "Cosa potrebbe ottenere un decodificatore da questi 4 personaggi?" (Li chiamerò a, b, c e d) e la mia idea iniziale era quella di ottenere 6 bit di informazioni dalle seguenti relazioni:

a>b
a>c
a>d
b>c
b>d
c>d

Wow, 6 bit, è perfetto! Ho pensato che fosse geniale, ma i test hanno dimostrato che non avrebbe funzionato. Esistono solo 24 combinazioni possibili. Dannazione.

Il passo successivo è stato provare a contare, in base a ciò che già sapevo. Quindi la prima lettera che appare nella stringa diventerebbe 0, quindi la seconda lettera introdotta nella stringa diventerebbe 1 e così via. Ma non mi porterebbe fino alle 62 combinazioni necessarie.

0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123

Ma mi piace comunque l'idea.

Bene, poi mi è sembrato di poter combinare questi due, perché i personaggi nell'input hanno già delle relazioni e non avrei dovuto aspettare fino a quando non fossero stati introdotti per dare loro un valore.

Come funziona

Nota: questo non è più esattamente il modo in cui funzionano le versioni golfate, ma il principio è rimasto lo stesso.

Per il decodificatore:

Viene costruito un array, il cui indice contiene tutti i numeri di quattro cifre la cui cifra più grande non è maggiore del numero di cifre distinte in quel numero. Esistono 75 numeri di quattro cifre diversi che soddisfano tale condizione. Li costringo brutalmente, perché finora non sono riuscito a trovare un modo per costruirli, e non sono sicuro che questo sarebbe più breve da fare in awk comunque. Mentre li trovo, assegno loro i personaggi costosi in ordine asciibetico.

Quindi sostituisco ogni carattere della stringa di input con una cifra. Il più piccolo (ad esempio 'B' più piccolo di 'a') diventa 1, il secondo più piccolo diventa 2 e così via fino a 4. Naturalmente dipende da quanti caratteri diversi sono presenti nell'input, qual è la cifra più alta in la stringa risultante sarà.

Quindi stampo semplicemente l'elemento array, che ha quella stringa come indice.

L'encoder funziona di conseguenza.

Come usare

Copia il codice direttamente in un comando awk bash line o crea due file "encode.awk" e "decode.awk" e incolla il codice di conseguenza. O ancora meglio usare il seguente codice, che esce automaticamente dopo en / decodifica, oppure può essere usato più volte rimuovendo il comando exit alla fine.

encode.awk

{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:0)++a[p];
            length(a)>=m&&i!~0?c[(x>9?55:48)+x++]=i:_
        }
    r=u=_; # clear reused variables 
    for(gsub(",",FS);sprintf("%c",++r)!=$NF;); # more flexible concerning
    --NF;                                      # spaces in input
    split($0,b);
    asort(b);
    split(c[r],a,_);
    for(j in a)u=u b[a[j]]; # prettier printing than golfed version
    print u
    exit # <=== remove to encode input file
}

decode.awk

{
    if(!x) # only do first time 
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:_)++a[p];
            length(a)>=m&&i!~0?c[i]=sprintf("%c",(x>9?55:48)+x++):_
        }
    delete t; delete d; o=_; # clear reused variables 
    split($1,a,_);
    for(i in a)t[a[i]]=1;
    for(i in t)d[++y]=i;
    asort(d);
    for(i in a)for(j in d)if(d[j]~a[i])o=o j;
    print c[o]
    exit # <=== remove to encode input file
}

Ecco un esempio di utilizzo:

me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X

Ricorda che è necessario lo spazio dopo ogni virgola, se usi le versioni golf.

Se lo desideri, puoi utilizzare questo script breve e sporco per generare alcuni dati di esempio

BEGIN{
    for(srand();i++<1000;)
    {
        erg="";
        for(j=0;j++<5;)
        {
            while(erg~(a[j]=substr(c="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",rand()*62+1,1)));
            erg=erg a[j]
        }
        print a[1]", "a[2]", "a[3]", "a[4]", "a[5](rand()>.5?" ":rand()>.5?"  ":"   ")substr(c,rand()*62+1,1)
    }
}

e fai qualcosa di divertente

me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62

L'ho visto più come un puzzle di programmazione. Penso che sia un po 'triste, che quasi tutto qui sia golfato, perché puoi imparare molto di più da un codice ben documentato e leggibile, ma questa è solo la mia opinione. E ho giocato a golf come richiesto;)


come testarlo? per favore condividi alcuni esempi.
Shravan Yadav,

+1 per la grande spiegazione! Sembra che ci siano molti modi diversi per affrontare questo problema :)
jrich

1
Questo è stato molto simile al mio processo di pensiero, tranne per il fatto che non mi ero reso conto che forzare brutalmente le uniche combinazioni deboli (in cui descrivevi che la cifra più grande non era maggiore della quantità di cifre) era un approccio praticabile. Complimenti per il seguito.
Patrick Roberts,
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.