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;)